提问人:Michael 提问时间:7/6/2017 更新时间:5/30/2019 访问量:9052
Enumerable.Repeat 用于引用类型对象初始化
Enumerable.Repeat for reference type objects initialization
问:
我有一个关于 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,如果我更改一个对象属性,所有其他对象也会更改它。
所以我的问题是:初始化引用类型对象是正确的方法吗?如果没有,那么什么是更好的方法?
答:
31赞
Kapol
7/6/2017
#1
使用这种方式将只初始化一个对象,并在每次循环访问结果时返回该对象。Enumerable.Repeat
这些对象在内存中是否具有相同的地址?
只有一个对象。
要实现您想要的,您可以这样做:
Enumerable.Range(1, 50).Select(i => new A()).ToArray();
这将返回一个包含 50 个不同对象的数组。A
顺便说一句,返回相同值的事实并不意味着对象在引用上是相等的(或者只是相等的)。两个不相等的对象可以具有相同的哈希代码。GetHashCode()
评论
0赞
Camilo Terevinto
7/6/2017
这很奇怪。我使用 Enumerable.Repeat 将对象复制几十次(因此我不必手动复制值),然后编辑我感兴趣的属性,它完美运行。所以,不太确定你说的“一个对象”是什么意思
1赞
Kapol
7/6/2017
来自 MSDN:“生成包含一个重复值的序列。 - 也许您使用的是值类型。在这种情况下,您每次都会得到一份副本。
0赞
Camilo Terevinto
7/6/2017
否,它们是同时具有 POCO 和嵌套类的 EF 实体
1赞
Kapol
7/6/2017
嗯。。。我刚刚对此进行了测试,并且按照我的假设工作:打印var x = Enumerable.Repeat(new C(), 2); Console.WriteLine(x[0] == x[1]);
true
1赞
johnnyRose
7/6/2017
@CamiloTerevinto referencesource.microsoft.com/#System.Core/System/Linq/......Kapol 是正确的 - 它将返回相同的元素 n 次。
7赞
Enigmativity
7/6/2017
#2
为了帮助澄清 Camilo,这里有一些测试代码显示了手头的问题:
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
评论
0赞
Camilo Terevinto
7/6/2017
感谢您的测试。我将不得不重新访问执行此操作的代码,我可能忘记了某些事情
1赞
Enigmativity
7/6/2017
@CamiloTerevinto - 不用担心。我只是认为这值得澄清。
2赞
Gusty Abra
5/30/2019
#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 循环来填充具有新引用类型的数组。
评论