2017-07-31 94 views
20

我一直使用C#了一段时间,但最近发现,我的单元测试一个的行为已发生更改,这取决于集合的变化初始化器表达我用:这两个集合初始化表达式的变体有什么区别?

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

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

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

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

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

class Foo 
{ 
    public List<int> Items { get; set; } 
} 

当我运行此,第一分配工作正常,但在NullReferenceException第二结果。

我的直觉是,幕后的编译器处理这两个词语,因为这:

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

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

是这个假设是否准确?

+0

,将帮助您:HTTP:/ /www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-iii/ –

回答

22

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

{ 
    Property = { ... } 
} 

而不是

{ 
    Property = expression 
} 

那么二传手的财产不使用 - 在吸气被使用,那么无论是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<int> { 1 }, 
    Property = new Bar { Value = 1 } 
}; 

这相当于:

// The setters for Collection and Property are called 
var foo = new Foo(); 
foo.Collection = new List<int> { 1 }; 
foo.Property = new Bar { Value = 1 }; 
+1

不应该等同于新的集合还是它只是添加? –