【问题标题】:Enumerable.Repeat for reference type objects initializationEnumerable.Repeat 用于引用类型对象的初始化
【发布时间】: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,如果我要更改一个对象的属性,所有其他对象也会更改它。

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

【问题讨论】:

    标签: c# reference-type


    【解决方案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 循环来用新的引用类型填充数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-31
      相关资源
      最近更新 更多