Estaba pensando en las matrices y las listas y me preguntaba si las clases pueden obtener una implementación inicializable como ellas y cómo. Tomemos esta clase como base:

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

    // Insert code here
}

Lo que me gustaría poder hacer es tomar los valores dados y completar internamente mi lista.

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

Lo que normalmente sería posible es esto:

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

Pero me gustaría tenerlo para mis propias clases personalizadas. La siguiente pregunta, que es opcional, es si se puede hacer lo mismo para esta sintaxis:

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

Supongo que es menos probable que sea posible. Tenga en cuenta que estos son diferentes de esto:

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

Estas son declaraciones directas y opcionales de campos internos y propiedades.

Consulte también MSDN para más información.

8
Battle 13 sep. 2018 a las 15:52

4 respuestas

La mejor respuesta

Como se indicó aquí, los inicializadores de colección funcionarán en cualquier clase que implemente IEnumerable y tenga un método Add().

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 ...
}

Tenga en cuenta que si tiene más de un parámetro en su firma de método Add(), puede encerrarlos entre llaves para usar la sintaxis del inicializador de colección.

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 ...
}

Sería usado así:

var test = new TestClass2 { {2, 3}, {4, 5} };
9
laptou 13 sep. 2018 a las 12:56

Técnicamente, los requisitos de mínimo son

  1. Interfaz IEnumerable (por supuesto, IEnumerable<T> es una mejor opción)
  2. Método Add

Ejemplo mínimo (solo demostración):

  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};  

En su caso:

  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();
    }
  }
4
Dmitry Bychenko 13 sep. 2018 a las 13:04

Solo necesita un método Add para que esto funcione e implementar la interfaz IEnumerable:

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();
    }
}

El compilador reconocerá la sintaxis del inicializador de la colección e intentará encontrar un método Add coincidente.

8
Patrick Hofman 13 sep. 2018 a las 12:55

Para responder a su segunda pregunta: si es posible hacer

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

No creo que esta sea la sintaxis correcta en ningún lado. Sin embargo, podría crear algo que se vea así usando el operador implícito.

Como puede crear una instancia de int array como esta: new[] {1,2,3,4}, puede crear lo siguiente en su TestClass.

public class TestClass {
   private IEnumerable<int> list;
   public TestClass(IEnumerable<int> _list) {
       this.list = _list;
   }

   public static implicit operator(int[] input) {
        return new TestClass(input.ToList());      
   }
}

Luego cree una nueva clase de prueba como esta; TestClass testClass = new[] {1,2,3};

1
Glubus 13 sep. 2018 a las 13:08