Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 515
Battle Avatar asked Sep 13 '18 12:09

Battle


People also ask

What is list initialization in C++?

List initialization is performed in the following situations: direct-list-initialization (both explicit and non-explicit constructors are considered) 1) initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)

How to initialize an array with the same value in C?

Below are some of the different ways in which all elements of an array can be initialized to the same value: Initializer List: To initialize an array in C with the same value, the naive way is to provide an initializer list. We use this with small arrays. This will initialize the num array with value 1 at all index.

What is the difference between brace initialization and class initialization in C++?

For Modern C++ there is also a third difference: the way brace initialization is handled. For a structure, brace initialization performs a direct initialization of its members For class types, brace initialization results in a call to a constructor. There’s nothing to stop you adding a constructor to a struct.

What happens if you brace initialization list in constructor?

If you do, the braced initialization list becomes a call to a constructor. struct POD { int i; int j; POD (int x, int y); }; int main () { POD pod1 { 1, 2 }; // POD::POD (1, 2); }


3 Answers

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} };
like image 186
laptou Avatar answered Nov 15 '22 15:11

laptou


You just need an Add method to make this work and implement the IEnumerable interface:

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

    public void Add(int n)
    {
        Numbers.Add(n);
    }

    public IEnumerator<int> GetEnumerator()
    {
        return Numbers.GetEnumerator();
    }

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

The compiler will recognize the collection initializer syntax and will try to find a matching Add method.

like image 20
Patrick Hofman Avatar answered Nov 15 '22 14:11

Patrick Hofman


Technically, the minimum requirements are

  1. IEnumerable interface (of course, IEnumerable<T> is a better choice)
  2. Add method

Minimum example (demonstration only):

  class TestClass: System.Collections.IEnumerable {
    public void Add(int value) { }

    public IEnumerator GetEnumerator() {
      // Just to demonstrate, do not do this in production code
      return null;
    }
  }

  ...

  TestClass myTest = new TestClass() {1, 2, 3};  

In your case:

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

    // This is required
    public void Add(int value) {
      Numbers.Add(value);
    }

    public IEnumerator<int> GetEnumerator() {
      return Numbers.GetEnumerator();
    }

    // This is required
    IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
    }
  }
like image 24
Dmitry Bychenko Avatar answered Nov 15 '22 14:11

Dmitry Bychenko