2015-12-21 74 views
5

假设,我们有一个非常简单的类:集合初始化的怪异语法

class ObjectList { 
    public List<string> List1 { get; } = new List<string>(); 
    public List<string> List2 { get; set; } 
} 

,我们想使这个类的一个实例:

ObjectList objectList = new ObjectList { 
    List1 = { "asdf", "qwer" }, 
    List2 = new List<string> { "zxcv", "1234" } 
}; 

所以,在列表2的情况下,好吧,使用“=”我们设置属性。但是,在List1的情况下,它看起来像我们设置属性,但实际上,我们假设在之前的某个位置设置它,并且在这里我们只设置值。它和数组初始化非常相似:

string[] arr = { "val1", "val2" } 

为什么C#在这里使用这种混淆语法?

编辑: 我想我很困惑与C#6.0语法的观众,但它不是重点。让我们使用旧的C#3.0和.net 2.0。并允许增添更多的乐趣也该增加一些值(“1”和“2”)的列表,从开始,杰夫梅尔卡多推荐:

class Program { 
    static void Main(string[] args) { 
     ObjectList objectList = new ObjectList { 
      List1 = { "asdf", "qwer" }, 
     }; 
    } 
} 
class ObjectList { 
    List<string> _List1 = new List<string>() { "1", "2" }; 
    public List<string> List1 { 
     get { 
      return _List1; 
     } 
    } 
} 

它显示了同样怪异的语法。最后,我列出了名单{“1”,“2”,“asdf”,“qwer”},这更加令人困惑。我可以期待这一点。

+1

编译? List1没有公共setter,所以你不应该在initializer语法中设置它。 –

+1

它的确如此。编译器实际上将该语法转换为调用'.Add()' –

+0

我同意,这种语法真的很奇怪。在语义上,它更像'+ ='。嵌套对象初始化器完全一样 - 没有构造函数调用,初始化器只设置属性。 –

回答

2

答案已经his answer to Why is an Add method required for { } initialization?被赋予通过Eric Lippert

的通过设计通过集合初始化典型使用场景激励的目标是使可能存在的集合类型的初始化表达式中的语法,使集合初始化可能嵌入在查询理解中或转换为表达式树。

每隔一个场景的优先级较低; 该功能完全存在,因为它有助于使LINQ工作

因此,即使在创建只读集合时该语法更有意义,它仍然被添加,因此它们可以按时交付LINQ。

+0

嗯..有趣的故事。但在LINQ中它有什么用处? –

+0

它在引用中说明了它的正确性:“在表达式语法中可以对现有集合类型进行初始化” –

+0

您可以提供一个示例吗?我想我从来没有这样用过,所以我有麻烦想象它。 –

3

为什么C#在这里使用这种混乱的语法?

你是对的,这有点奇怪,但那是因为你混合了2个原则。正如几个意见已经指出的那样,当=左边的项目是集合时,{ item1, items2 }语法被转换为.Add(itemN)调用

所以怪事是那

List<SomeClass> list = new List<SomeClass> { item1, item2 }; 
SomeClass[] array = { item1, item2 }; 

区别对待事实的结果。

另一部分是你的样本移动new List<SomeClass>左右,但它在两种情况下。

+1

我宁愿说奇怪是赋值运算符('=')没有做任何赋值的结果。 –

+0

我还没有完整的图片。 C#,所有语言。看起来非常整齐,但分配.add()看起来像是一种语言中的错误。 C#团队必须有一个非常严肃的理由来添加这个,我想知道它。 –