Enumerable.Repeat 用于引用类型对象的初始化

Posted

技术标签:

【中文标题】Enumerable.Repeat 用于引用类型对象的初始化【英文标题】:Enumerable.Repeat for reference type objects initialization 【发布时间】:2017-12-09 18:06:37 【问题描述】:

我有一个关于 Enumerable.Repeat 函数的问题。

如果我要上课:

class A

//code

我将创建一个数组,该类型的对象:

A [] arr = new A[50];

接下来,我将要初始化这些对象,调用 Enumerable.Repeat:

arr = Enumerable.Repeat(new A(), 50);

这些对象在内存中的地址是否相同? 如果我想检查他们的哈希码,例如以这种方式:

bool theSameHashCode = questions[0].GetHashCode() == questions[1].GetHashCode();

这将返回 true,如果我要更改一个对象的属性,所有其他对象也会更改它。

所以我的问题是:这是初始化引用类型对象的正确方式吗?如果没有,那还有什么更好的方法?

【问题讨论】:

【参考方案1】:

以这种方式使用Enumerable.Repeat 只会初始化一个对象,并在每次迭代结果时返回该对象。

这些对象在内存中的地址是否相同?

只有一个对象。

要实现你想要的,你可以这样做:

Enumerable.Range(1, 50).Select(i => new A()).ToArray();

这将返回一个包含 50 个不同类型的 A 对象的数组。

顺便说一句,GetHashCode() 返回相同的值这一事实并不意味着对象在引用上是相等的(或者简单地相等)。两个不相等的对象可以有相同的哈希码。

【讨论】:

这很奇怪。我使用 Enumerable.Repeat 复制一个对象几十次(所以我不必手动复制值),然后编辑我感兴趣的属性,它完美地工作。所以,不太清楚你所说的“一个对象”是什么意思 来自 MSDN:“生成包含一个重复值的序列。” - 也许你正在使用值类型。在这种情况下,您每次都会得到一份副本。 不,它们是具有 POCO 和嵌套类的 EF 实体 嗯...我刚刚对此进行了测试并按照我的假设工作:var x = Enumerable.Repeat(new C(), 2); Console.WriteLine(x[0] == x[1]); 打印 true @CamiloTerevinto referencesource.microsoft.com/#System.Core/System/Linq/… Kapol 是正确的 - 它会返回相同的元素 n 次。【参考方案2】:

只是为了帮助卡米洛澄清,这里有一些测试代码显示了手头的问题:

void Main()

    var foos = Enumerable.Repeat(new Foo(), 2).ToArray();
    foos[0].Name = "Jack";
    foos[1].Name = "Jill";
    Console.WriteLine(foos[0].Name);    


public class Foo

    public string Name;

这将打印“吉尔”。因此它表明Enumerable.Repeat 只创建了Foo 类的一个实例。

【讨论】:

感谢您的测试。我将不得不重新访问执行此操作的代码,我可能忘记了一些事情 @CamiloTerevinto - 不用担心。我只是认为这值得澄清。【参考方案3】:

当使用以下代码创建数组时:

var foos = Enumerable.Repeat(new Foo(), 2).ToArray();

数组中每个位置都相同的原因是因为你传递的是一个对象,而不是一个创建对象的函数,上面的代码是一样的:

var foo = new Foo();
var foos = Enumerable.Repeat(foo , 2).ToArray();

上述原因也解释了为什么使用 Select 语句(如下面的代码)为每个条目创建一个新对象,因为您传递的是一个函数,该函数指示每个对象的创建方式,而不是对象本身。

Enumerable.Range(1, 2).Select(i => new Foo()).ToArray();

我会使用一个简单的 for 循环来用新的引用类型填充数组。

【讨论】:

以上是关于Enumerable.Repeat 用于引用类型对象的初始化的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 C# 中使用 Enumerable.Repeat 方法重复 Func<T, T> ?

JAVA类型有基础变量类型引用类型。

我们应该将 Tuple 或 ValueTuple 用于仅引用类型的变量吗?

C++基础--引用

constructor VS object

创建一个链接三种不同节点类型和两个节点引用的视图