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> ?