C# Enumerable.Repeat() 的小坑

其实也不算 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() 内部并没有对类型进行判断,只是简单的返回指定数量的元素

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据