Search code examples
c#collection-initializer

Initialize elements with brackets like Lists in c#


I was thinking about arrays and lists and wondering if and how classes can get an implementation to be initializable like them. Let's take this class as basis:

class TestClass
{
    private List<int> Numbers = new List<int> ();

    // Insert code here
}

What I would like to be able to do is to take the given values and internally fill my list.

TestClass test = new TestClass () { 2, 4, 7, 10 };

What would be normally possible is this:

List<int> test = new List<int> () { 2, 4, 7, 10 };

But I would like to have it for my own custom classes. The next question, which is optional, is if the same can be done for this syntax:

TestClass test = { 2, 4, 7, 10 };

I assume that is less likely to be possible. Note, these are different from this:

Cat cat = new Cat() { Name = "Sylvester", Age=8 };

These are direct and optional declarations of internal fields and properties.

See also MSDN for more info.


Solution

  • As stated here, collection initialisers will work on any class that implements IEnumerable and has an Add() method.

    class TestClass : IEnumerable<int>
    {
        private List<int> Numbers = new List<int> ();
    
        public void Add(int n)
        {
            Numbers.Add(n);
        }
    
        // implement IEnumerable methods down here ...
    
        public IEnumerator<int> GetEnumerator() => Numbers.GetEnumerator();
    
        // etc ...
    }
    

    Note that if you have more than one parameter in your Add() method signature, then you can enclose them in curly braces to use collection initialiser syntax.

    class TestClass2 : IEnumerable<(int, int)>
    {
        private List<int> Numbers = new List<(int, int)> ();
    
        public void Add(int x, int y)
        {
            Numbers.Add((x, y));
        }
    
        // implement IEnumerable methods down here ...
    
        public IEnumerator<(int, int)> GetEnumerator() => Numbers.GetEnumerator();
    
        // etc ...
    }
    

    Would be used like this:

    var test = new TestClass2 { {2, 3}, {4, 5} };