Custom collection initializers

Classes that implement IEnumerable and provide the function public void Add(/* args */) can be initialized, as in the following example:

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

which calls the Add(int) 3x function after initializing the List<int> .

Is there a way to explicitly define this behavior for my own classes? For example, can I initialize a function call other than the corresponding Add() overload?

+42
c #
Mar 22 '10 at 21:12
source share
2 answers

No, the compiler requires the use of the Add method to initialize the collection. This is defined in the C # specification and cannot be changed:

C # language specification - 7.5.10.3 Collection initializers

The collection object to which the collection initializer is applied must be of a type that implements System.Collections.IEnumerable or a compile-time error occurs. For each given element, in order, the collection initializer calls the Add method of the target object with a list of element initializer expressions as a list of arguments, using the normal overload resolution for each call. Thus, the collection object must contain the applicable Add method for each element initializer. [emphasis mine]

Of course, the Add method can take more than one argument (for example, 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); 
+54
Mar 22 '10 at 21:13
source share

Adding as an example the answer of what works. AFAIK, only Add will work. Code snippet taken from 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 } }; 
+4
Nov 25 '15 at 23:37
source share



All Articles