今天我很惊讶地发现在C#中我能做到:
List<int> a = new List<int> { 1, 2, 3 };
为什么我能这样做?调用什么构造函数?我怎么能用我自己的课程做到这一点?我知道这是初始化数组的方法,但数组是语言项,列表是简单的对象......
答案 0 :(得分:182)
这是.NET中集合初始化程序语法的一部分。您可以在创建的任何集合上使用此语法,只要:
它实现了IEnumerable
(最好是IEnumerable<T>
)
它有一个名为Add(...)
调用默认构造函数会发生什么,然后为初始化程序的每个成员调用Add(...)
。
因此,这两个块大致相同:
List<int> a = new List<int> { 1, 2, 3 };
和
List<int> temp = new List<int>();
temp.Add(1);
temp.Add(2);
temp.Add(3);
List<int> a = temp;
如果您愿意,可以调用备用构造函数,例如,防止在成长期间List<T>
过大,等等:
// Notice, calls the List constructor that takes an int arg
// for initial capacity, then Add()'s three items.
List<int> a = new List<int>(3) { 1, 2, 3, }
请注意,Add()
方法不需要使用单个项目,例如Add()
的{{1}}方法需要两个项目:
Dictionary<TKey, TValue>
大致相同:
var grades = new Dictionary<string, int>
{
{ "Suzy", 100 },
{ "David", 98 },
{ "Karen", 73 }
};
因此,要将此添加到您自己的类中,您所需要做的就是实现var temp = new Dictionary<string, int>();
temp.Add("Suzy", 100);
temp.Add("David", 98);
temp.Add("Karen", 73);
var grades = temp;
(再次,最好是IEnumerable
)并创建一个或多个IEnumerable<T>
方法:
Add()
然后就像BCL集合那样使用它:
public class SomeCollection<T> : IEnumerable<T>
{
// implement Add() methods appropriate for your collection
public void Add(T item)
{
// your add logic
}
// implement your enumerators for IEnumerable<T> (and IEnumerable)
public IEnumerator<T> GetEnumerator()
{
// your implementation
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
(有关详细信息,请参阅MSDN)
答案 1 :(得分:11)
它被称为syntactic sugar。
List<T>
是“简单”类,但编译器会对其进行特殊处理,以使您的生活更轻松。
这个被称为collection initializer。您需要实施IEnumerable<T>
和Add
方法。
答案 2 :(得分:8)
根据C# Version 3.0 Specification“应用集合初始化程序的集合对象必须是一个实现System.Collections.Generic.ICollection的类型,只有一个T.”
但是,在撰写本文时,此信息似乎不准确;请参阅Eric Lippert在下面评论中的澄清。
答案 3 :(得分:6)
这要归功于collection initializers,它基本上要求集合实现Add方法,并为您完成工作。
答案 4 :(得分:6)
关于集合初始化器的另一个很酷的事情是,你可以有多个Add
方法的重载,你可以在同一个初始化器中调用它们!例如,这有效:
public class MyCollection<T> : IEnumerable<T>
{
public void Add(T item, int number)
{
}
public void Add(T item, string text)
{
}
public bool Add(T item) //return type could be anything
{
}
}
var myCollection = new MyCollection<bool>
{
true,
{ false, 0 },
{ true, "" },
false
};
它调用正确的重载。此外,它只查找名为Add
的方法,返回类型可以是任何内容。
答案 5 :(得分:0)
类似语法的数组正在进行一系列Add()
次调用。
要在更有趣的示例中看到这一点,请考虑以下代码,其中我执行两个有趣的事情,这些事情在C#中首先是非法的,1)设置readonly属性,2)使用像初始化程序这样的数组设置列表。
public class MyClass
{
public MyClass()
{
_list = new List<string>();
}
private IList<string> _list;
public IList<string> MyList
{
get
{
return _list;
}
}
}
//In some other method
var sample = new MyClass
{
MyList = {"a", "b"}
};
这段代码可以很好地工作,虽然1)MyList是只读的,2)我用数组初始化器设置了一个列表。
这种方法之所以有效,是因为在作为对象初始化程序一部分的代码中,编译器总是将任何{}
类似的语法转换为一系列Add()
调用,这些调用即使在readonly上也是完全合法的字段。