为什么{}初始化需要Add方法?

时间:2011-01-13 14:42:28

标签: c# syntax initializer

使用这样的初始化语法:

var contacts = new ContactList
{
    { "Dan", "dan.tao@email.com" },
    { "Eric", "ceo@google.com" }
};

...我的理解是我的ContactList类型would need to define an Add method需要两个string参数:

public void Add(string name, string email);

对我来说有点困惑的是{ }初始化程序语法在创建只读或固定大小的集合时似乎最有用。毕竟它意味着模仿数组的初始化语法,对吗? (好吧,所以数组不是只读的;但是它们固定大小。)当然,它只能在编译时知道集合的内容(至少是元素的数量)时使用

因此,似乎使用此集合初始化程序语法(具有Add方法并因此具有可变集合)的主要要求与其最有用的典型情况不一致。

我确信我没有像C#设计团队那样考虑这个问题;看起来这个语法可能会有不同的规则,这些规则可以与其典型的使用场景进行更好的网络化。

我离开基地吗?是否希望使用{ }语法来初始化固定大小的集合,这不像我想的那么常见?还有哪些其他因素可能会影响我对这种语法的要求的制定,而我根本就没有考虑过?

9 个答案:

答案 0 :(得分:10)

  

我确信我没有像C#设计团队那样考虑这个问题;看起来这个语法可能会有不同的规则,这些规则可以与其典型的使用场景进行更好的网络化。

你的分析非常好;关键问题是上述陈述中的最后三个字。什么是实际的典型使用方案

集合初始化程序的典型使用方案所激发的设计目标是在表达式语法中实现现有集合类型初始化这样集合初始值设定项可以嵌入查询理解转换为表达式树

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

C#3编译器团队是Visual Studio / .NET发布的“长极” - 我们在任何团队的日程安排上都有大部分工作时间,这意味着每天我们推迟,产品将是延迟。我们想为所有人按时发运优质产品,完美是好的敌人。是的,这个功能略显笨重,并没有完全做到你想要的所有内容,但更重要的是让它变得坚固并经过LINQ测试,而不是让它适用于一大堆不可变的集合类型甚至存在

如果从第一天开始将这个功能设计到语言中,,而框架类型仍在不断发展,我确信事情会有所不同。正如我们在本网站的其他地方所讨论的那样,我非常希望拥有一次写入多次读取固定大小的数组值。定义一个公共模式以提供一堆状态来初始化任意不可变集合会很不错。你是对的,集合初始化器语法对于这样的事情是理想的。

此类功能列在未来潜在的hyptothetical语言版本列表中,但在列表中并不是真正的高位。换句话说,在我们认为对于不可变集合初始化的语法糖太难之前,让我们首先得到异步/等待。

答案 1 :(得分:3)

这是因为初始化语句是CLR的简写。当它被编译成字节码时,它将调用你定义的Add方法。

因此,你可以证明这个初始化语句实际上不是“第一类”特性,因为它在IL中没有对应物。但是我们使用的很多东西就是这种情况,例如“使用”语句。

答案 2 :(得分:2)

主要原因是Syntactic Sugar

初始化语法只能使编写C#中的编程更容易一些。它实际上并没有为语言添加任何表达能力。

如果初始化程序不需要Add()方法,那么它将是一个与现在完全不同的功能。基本上,它不是C#的工作方式。没有用于创建常规集合的文字形式。

答案 3 :(得分:2)

严格来说,这不是一个答案,但如果你想知道什么样的东西影响了收藏初始化者的设计,那么你可能会觉得这很有趣:

答案 4 :(得分:2)

原因是它被改装了。我同意你的观点,使用构造函数获取集合会更有意义,但并非所有现有集合类都实现了这一点,并且更改应该(1)适用于所有现有集合,(2)不更改任何现有类方式。

这是妥协。

答案 5 :(得分:1)

如果不是Add方法,初始化语法应该使用什么?在运行集合的构造函数之后,初始化语法为“run”,并且集合已完全创建。在创建集合后,必须有一些方式将项目添加到集合中。

如果要初始化只读集合,请在构造函数中执行此操作(使用T[] items参数或类似参数)

答案 6 :(得分:1)

据我了解,集合初始化程序语法只是syntactic sugar,没有特殊的技巧。它的设计部分是为了支持在Linq查询中初始化集合:

from a in somewhere
select new {
   Something = a.Something
   Collection = new List<object>() {
      a.Item1,
      a.Item2,
      ...
   }
}

在没有办法进行此内联之前,你必须在案件之后这样做,这很烦人。

答案 7 :(得分:1)

我很想拥有不可变类型(集合和普通类型)的初始化语法。我认为这可以使用类似于params的语法通过特殊的构造函数重载来实现。

例如:

MyClass(initializer KeyValuePair<K,V>[] initialValues)

但不幸的是,C#团队还没有实现这样的事情:(

所以我们需要使用像

这样的解决方法
MyClass(new KeyValuePair<K,V>[]{...})

现在

答案 8 :(得分:1)

集合初始值设定项是表达式,因此只有表达式有效时才能使用它们,例如字段初始值设定项或LINQ查询。这使他们的存在非常有用。

我还认为卷曲括号{ }类型的初始化,更像是一个固定大小的集合,但它只是一个语法选择。