una que programacion objetos metodos metodo lista instanciar inicializador ejemplos crear como clases clase c# collections

que - lista de objetos c#



¿Por qué los inicializadores de colección C#funcionan de esta manera? (3)

(Sé que tengo 3 años de retraso en esto, pero no estaba satisfecho con las respuestas existentes).

¿Por qué, para que compile esta sintaxis, el compilador no requiere que el tipo implemente ICollection?

Voy a revertir su pregunta: ¿de qué serviría si el compilador tuviera requisitos que realmente no son necesarios?

Las clases que no sean ICollection también pueden beneficiarse de la sintaxis del inicializador de recopilación. Considere las clases que permiten agregar datos en ellos, sin permitir el acceso a datos previamente agregados.

Personalmente, me gusta usar la new Data { { ..., ... }, ... } sintaxis de new Data { { ..., ... }, ... } para agregar una apariencia ligera y similar al DSL al código de mis pruebas unitarias.

En realidad, prefiero debilitar el requisito, de modo que pueda usar la sintaxis de aspecto agradable sin siquiera tener que preocuparme de implementar IEnumerable . Los inicializadores de colecciones son azúcar sintáctico puro para Agregar (), no deberían requerir nada más.

Estaba mirando los inicializadores de colecciones C # y encontré que la implementación es muy pragmática pero también muy diferente a cualquier otra cosa en C #

Puedo crear código como este:

using System; using System.Collections; class Program { static void Main() { Test test = new Test { 1, 2, 3 }; } } class Test : IEnumerable { public IEnumerator GetEnumerator() { throw new NotImplementedException(); } public void Add(int i) { } }

Como he cumplido los requisitos mínimos para el compilador (implementado IEnumerable y un public void Add ), esto funciona, pero obviamente no tiene ningún valor.

Me preguntaba qué impedía que el equipo de C # creara un conjunto más estricto de requisitos. En otras palabras, ¿por qué, para que esta sintaxis se compile, el compilador no requiere que el tipo implemente ICollection ? Eso parece más en el espíritu de otras características de C #.


Pensé en esto también, y la respuesta que más me satisface es que ICollection tiene muchos métodos además de Agregar, como: Borrar, Contiene, CopiarA y Eliminar. La eliminación de elementos o el borrado no tiene nada que ver con la capacidad de soportar la sintaxis del inicializador de objetos, todo lo que necesita es un Add ().

Si el marco se diseñó de forma granular y existía una interfaz ICollectionAdd, habría tenido un diseño "perfecto". Pero, sinceramente, no creo que hubiera agregado mucho valor, teniendo un método por interfaz. IEnumerable + Add parece un enfoque hackish, pero cuando lo piensas, es una mejor alternativa.

EDITAR: Esta no es la única vez que C # ha abordado un problema con este tipo de solución. Desde .NET 1.1, foreach usa tipado de pato para enumerar una colección, toda su clase necesita implementar es GetEnumerator, MoveNext y Current. Kirill Osenkov tiene una publicación que también hace su pregunta.


Su observación es perfecta, de hecho, refleja una hecha por Mads Torgersen, un Microsoft C # Language PM.

Mads hizo una publicación en octubre de 2006 sobre este tema titulado ¿Qué es una colección? en el cual él escribió:

Admitido, lo arruinamos en la primera versión del framework con System.Collections.ICollection, que es inútil. Pero lo solucionamos bastante bien cuando aparecieron los genéricos en .NET framework 2.0: System.Collections.Generic.ICollection <T> le permite agregar y quitar elementos, enumerarlos, contarlos y verificar la membresía.

Obviamente, a partir de ese momento, todos implementarán ICollection <T> cada vez que hagan una colección, ¿verdad? No tan. Así es como usamos LINQ para aprender sobre qué colecciones realmente son, y cómo eso nos hizo cambiar nuestro diseño de lenguaje en C # 3.0.

Resulta que solo hay 14 implementaciones de ICollection<T> en el marco, pero 189 clases que implementan IEnumerable y tienen un método público Add() .

Este enfoque tiene un beneficio oculto: si lo hubieran basado en la ICollection<T> , habría habido exactamente un método compatible con Add() .

En contraste, el enfoque que tomaron significa que los inicializadores de la colección solo forman conjuntos de argumentos para los métodos Add() .

Para ilustrar, extendamos un poco tu código:

class Test : IEnumerable { public IEnumerator GetEnumerator() { throw new NotImplementedException(); } public void Add(int i) { } public void Add(int i, string s) { } }

Ahora puede escribir esto:

class Program { static void Main() { Test test = new Test { 1, { 2, "two" }, 3 }; } }