其实也不算 Enumerable.Repeat() 的坑,算是值/引用类型的坑
其实也不算坑,只是之前没了解过,所以踩坑里了
假设使用 Enumerable.Repeat() 创建交错数组 arr
int[][] arr = Enumerable.Repeat(new int[123], 123).ToArray();
这样看似 arr 是一个有 123 行 123 列的交错数组,现在尝试更改第一个元素的值
arr[0][0] = 123
之后输出所有元素就会发现,每行的第一个元素都被更改为 123 了,预想情况下应该只有第一行第一列的元素是 123,其余都是 0(默认值)
这是因为在 C# 中数组是引用类型,数组变量是指向内存区域的内存地址
在之前的代码中,Enumerable.Repeat() 实际上返回了123 个 new int[123] 数组的引用(内存地址),对任意一行做的任何更改都作用在同一个 123 长度的实例上
如果想正常生成 123 个 123 长度的数组,需要添加 Select() LINQ,更改为
int[][] arr = Enumerable.Repeat(0, 123).Select(i => new int[123]).ToArray();
或者直接用循环
对于所有引用类型的值都需要这样操作(关于引用类型:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types)
而对于值类型,Enumerable.Repeat() 会正常返回指定数量个实例(关于值类型:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types)
通过 Enumerable.Repeat() 源代码 可以看出,Enumerable.Repeat() 内部并没有对类型进行判断,只是简单的返回指定数量的元素