自定义集合初始化器

时间:2010-03-22 21:12:09

标签: c#

可以初始化实现IEnumerable并提供public void Add(/* args */)函数的类,如下例所示:

List<int> numbers = new List<int>{ 1, 2, 3 };

在初始化Add(int)后调用List<int>函数。

有没有办法为我自己的类显式定义这种行为?例如,我可以让初始化程序调用除适当的Add()重载之外的函数吗?

2 个答案:

答案 0 :(得分:63)

不,编译器需要一个名为Add的方法才能使集合初始化程序起作用。这是在C#规范中定义的,不能更改:

  

C#语言规范 - 7.5.10.3集合初始化程序

     

应用集合初始值设定项的集合对象必须是实现System.Collections.IEnumerable的类型,否则会发生编译时错误。对于按顺序的每个指定元素,集合初始值设定项在目标对象上调用Add方法,并将元素初始值设定项的表达式列表作为参数列表,为每个调用应用正常的重载决策。因此, 集合对象必须包含适用于每个元素初始值设定项的Add方法 [强调我的]

当然,Add方法可以使用多个参数(例如Dictionary<TKey, TValue>):

dic = new Dictionary<int, int> { 
    { 1, 2 },
    { 3, 4 }
};
// translated to:
dic = new Dictionary<int, int>();
dic.Add(1, 2);
dic.Add(3, 4);

答案 1 :(得分:4)

添加一个有效的示例答案。 AFAIK,只有Add才有效。摘自Marius Schulz

的代码段
// simple struct which represents a point in three-dimensional space
public struct Point3D
{
    public readonly double X;
    public readonly double Y;
    public readonly double Z;

    public Point3D(double x, double y, double z)
    {
        X = x;
        Y = y;
        Z = z;
    }
}

// implementation of a collection of points, which respects
// the compiler convention for collection initializers and
// therefore both implements IEnumerable<T> and provides
// a public Add method
public class Points : IEnumerable<Point3D>
{
    private readonly List<Point3D> _points;

    public Points()
    {
        _points = new List<Point3D>();
    }

    public void Add(double x, double y, double z)
    {
        _points.Add(new Point3D(x, y, z));
    }

    public IEnumerator<Point3D> GetEnumerator()
    {
        return _points.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

// instantiate the Points class and fill it with values like this:
var cube = new Points
{
    { -1, -1, -1 },
    { -1, -1,  1 },
    { -1,  1, -1 },
    { -1,  1,  1 },
    {  1, -1, -1 },
    {  1, -1,  1 },
    {  1,  1, -1 },
    {  1,  1,  1 }
};