集合初始化表达式的这两个变体之间有什么区别?

Tagc 09/16/2017. 1 answers, 803 views
c# collection-initializer

我一直在使用C#,但最近注意到我的一个单元测试的行为取决于我使用的集合初始表达式的变化:

  • var object = new Class { SomeCollection = new List { 1, 2, 3 } };
  • var object = new Class { SomeCollection = { 1, 2, 3 } };

直到这一点,我认为第二种形式只是语法糖,在语义上等同于第一种形式。 然而,在这两种形式之间切换导致我的单元测试通过失败。

下面的示例代码演示了这一点:

 void Main()
{
    var foo1 = new Foo { Items = new List { 1, 2, 3} };
    var foo2 = new Foo { Items = { 1, 2, 3 } };

    foo1.Dump();
    foo2.Dump();
}

class Foo
{
    public List Items { get; set; }
} 

当我运行这个时,第一个赋值工作正常,但第二个赋值为NullReferenceException

我的直觉是编译器在幕后处理这两个表达式:

 var foo1 = new Foo();
foo1.Items = new List { 1, 2, 3 }; 

var foo2 = new Foo();
foo2.Items.Add(1);
foo2.Items.Add(2);
foo2.Items.Add(3); 

这个假设是否准确?

1 Comments
Leon Barkan 07/31/2017
这将帮助你: c-sharpcorner.com/article/...

1 Answers


Jon Skeet 07/31/2017.

是的,你的假设是准确的。 如果一个对象初始化器只有:

{
    Property = { ... }
} 

而不是

{
    Property = expression
} 

那么属性的setter不会被使用 - 使用getter ,然后调用Add方法,或者在返回的值中设置属性。 所以:

var foo = new Foo
{
    Collection = { 1 }
    Property =
    {
        Value = 1
    }
}; 

相当于:

// Only the *getters* for Collection and Property are called
var foo = new Foo();
foo.Collection.Add(1);
foo.Property.Value = 1; 

比较:

var foo = new Foo
{
    Collection = new List { 1 },
    Property = new Bar { Value = 1 }
}; 

相当于:

// The setters for Collection and Property are called
var foo = new Foo();
foo.Collection = new List { 1 };
foo.Property = new Bar { Value = 1 }; 
1 comments
1 Ash Burlaczenko 07/31/2017
不应该等同于新的集合,还是它只是添加?

Related questions

Hot questions

Language

Popular Tags