utilizar matriz llenar inicializar imprimir guardar generar enteros declarar datos como caracteres arreglo array c# syntax initialization magic-methods

llenar - imprimir matriz c#



¿Cómo hacer que la inicialización del arreglo en línea funcione, por ejemplo, mediante la inicialización del diccionario? (6)

¿Por qué es posible inicializar un Dictionary<T1,T2> como este:

var dict = new Dictionary<string,int>() { { "key1", 1 }, { "key2", 2 } };

... pero no para inicializar, por ejemplo, una matriz de KeyValuePair<T1,T2> exactamente de la misma manera:

var kvps = new KeyValuePair<string,int>[] { { "key1", 1 }, { "key2", 2 } }; // compiler error: "Array initializers can only be used in a variable // or field initializer. Try using a new expression instead."

Me doy cuenta de que podría hacer que el segundo ejemplo funcione escribiendo simplemente new KeyValuePair<string,int>() { "key1", 1 } , etc. para cada elemento. Pero me pregunto si es posible usar el mismo tipo de sintaxis concisa que es posible en el primer ejemplo.

Si no es posible, ¿qué hace que el tipo de diccionario sea tan especial?


Funciona con el Diccionario, porque tiene una sobrecarga para Add que toma dos argumentos. Las matrices ni siquiera tienen un método Add , y mucho menos uno con dos argumentos.

La clase Dictionary está especialmente diseñada para trabajar con KeyValuePair<,> internamente, esa es la única razón por la que no necesita llamar al constructor manualmente, en su lugar se llama al Add dos argumentos y construye el KeyValuePair bajo el capó.

Todos los demás IEnumerable<KeyValuePair<,>> no tienen esta implementación especial y, por lo tanto, deben inicializarse de esta manera:

var array = new KeyValuePair<int, int>[] { new KeyValuePair<int, int>(1, 2), new KeyValuePair<int, int>(3, 4) };

Puede crear el mismo comportamiento con sus propias clases, como digamos que implementa esto:

class ThreeTupleList<T1, T2, T3> : List<Tuple<T1, T2, T3>> { public void Add(T1 a, T2 b, T3 c) { this.Add(new Tuple<T1, T2, T3>(a, b, c)); } // You can even implement a two-argument Add and mix initializers public void Add(T1 a, T2 b) { this.Add(new Tuple<T1, T2, T3>(a, b, default(T3))); } }

puedes inicializarlo así, e incluso mezclar inicializadores de tres, dos y un argumento:

var mylist = new ThreeTupleList<int, string, double>() { { 1, "foo", 2.3 }, { 4, "bar", 5.6 }, { 7, "no double here" }, null };


Gracias a múltiples contestadores para señalar que el método Add es la salsa secreta mágica que hace funcionar la sintaxis de inicialización. Así que pude lograr mi objetivo heredando la clase en cuestión (KeyValuePair):

public class InitializableKVPs<T1,T2> : IEnumerable<KeyValuePair<T1,T2>> { public void Add(T1 key, T2 value) { throw new NotImplementedException(); } public IEnumerator<KeyValuePair<string,string>> GetEnumerator() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } }

Esto ahora es aceptado por el compilador:

var kvps = new InitializableKVPs<string,int> { { "key1", 1 }, { "key2", 2 } };

Editar : La respuesta de Philip Daubmeier tiene una implementación real y concisa de esto.


La sintaxis del inicializador de recopilación se traduce en llamadas a Add con la cantidad adecuada de parámetros:

var dict = new Dictionary<string,int>(); dict.Add("key1", 1); dict.Add("key2", 2);

Esta sintaxis de inicializador especial también funcionará en otras clases que tengan un método Add e implemente IEnumerable . Creemos una clase completamente loca solo para demostrar que no hay nada especial acerca de Dictionary y que esta sintaxis puede funcionar para cualquier clase adecuada:

// Don''t do this in production code! class CrazyAdd : IEnumerable { public void Add(int x, int y, int z) { Console.WriteLine(x + y + z); // Well it *does* add... } public IEnumerator GetEnumerator() { throw new NotImplementedException(); } }

Ahora puedes escribir esto:

var crazyAdd = new CrazyAdd { {1, 2, 3}, {4, 5, 6} };

Productos:

6 15

Véalo trabajar en línea: ideone

En cuanto a los otros tipos sobre los que preguntaste:

  • No funciona en una matriz porque no tiene un método Add .
  • List<T> tiene un método Add , pero solo tiene un parámetro.

Puede que no lo veas, pero es la misma sintaxis. La única diferencia es que una matriz toma elementos como una entrada donde un diccionario toma una matriz bidimensional.

int[] a = new int[]{5,6}; int[,] a = new int[]{{5,6},{3,6}}; Dictionary<int,int> a = new Dictionary<int,int>{{5,6},{3,6}};


Su problema proviene del hecho de que es una matriz, no una colección.

var kvps = new KeyValuePair<string,int>[] { { "key1", 1 }, { "key2", 2 } };

debería ser realmente:

var kvps = new KeyValuePair<string, int>[] { new KeyValuePair<string, int>("key1", 1), new KeyValuePair<string, int>("key2", 2) };

El sorteo es los corchetes. [] es una matriz. {} es una colección.


Anular IDictionary para la sintaxis de C # 6.0

En caso de que alguien venga aquí, como lo hice, buscando guardar algunas pulsaciones de teclado para la nueva sintaxis del inicializador del diccionario C # 6.0, se puede hacer, pero requiere derivar de IDictionary en su lugar. Solo necesita implementar el método this [] set para que esto funcione, lo que deja una tonelada de métodos no implementados.

La implementación de la clase se ve así:

// Seriously! Don''t do this in production code! Ever!!! public class CrazyAdd2 : IDictionary<string, int> { public int this[string key] { get { throw new NotImplementedException(); } set {Console.WriteLine($"([{key}]={value})"); } } #region NotImplemented // lots of empty methods go here #endregion }

luego para usarlo:

var crazyAdd2 = new CrazyAdd2 { ["one"] = 1, ["two"] = 2, };

y el resultado:

([one]=1) ([two]=2)

Y aquí hay un violín que demuestra todo:

https://dotnetfiddle.net/Lovy7m