Sé que IList es la interfaz y List es el tipo concreto, pero todavía no sé cuándo usar cada uno. Lo que estoy haciendo ahora es que si no necesito los métodos de Ordenar o Buscar Todos, uso la interfaz. ¿Estoy en lo cierto? ¿Hay una mejor manera de decidir cuándo usar la interfaz o el tipo concreto?
Hay dos reglas que sigo:
Por lo tanto, al escribir una función o método que toma una colección, escríbala para no tomar una lista, sino un IList
Por otro lado, cuando se devuelve un objeto de una función, se desea darle al usuario el conjunto de operaciones más completo posible sin que tenga que dar vueltas. Entonces, en ese caso, si es una Lista
Las pautas de Microsoft comprobadas por FxCop desalientan el uso de List
Por cierto, ahora casi siempre declaro matrices unidimensionales como IList
public interface IMyApi { IList GetReadOnlyValues(); } public class MyApiImplementation : IMyApi { public IList GetReadOnlyValues() { List myList = new List (); ... populate list return myList.AsReadOnly(); } } public class MyMockApiImplementationForUnitTests : IMyApi { public IList GetReadOnlyValues() { IList testValues = new int[] { 1, 2, 3 }; return testValues; } }
Hay algo importante que las personas siempre parecen pasar por alto:
Puede pasar una matriz simple a algo que acepte un parámetro IList
, y luego puede llamar a IList.Add()
y recibirá una excepción en tiempo de ejecución:
Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
Por ejemplo, considere el siguiente código:
private void test(IList list) { list.Add(1); }
Si llama a eso de la siguiente manera, obtendrá una excepción de tiempo de ejecución:
int[] array = new int[0]; test(array);
Esto sucede porque el uso de matrices simples con IList
viola el principio de sustitución de Liskov.
Por este motivo, si llama a IList
, puede considerar la posibilidad de solicitar una List
lugar de una IList
.
Estoy de acuerdo con el consejo de Lee de tomar los parámetros, pero no regresar.
Si especifica sus métodos para devolver una interfaz, significa que puede cambiar la implementación exacta más adelante sin que el método consumidor lo sepa. Pensé que nunca necesitaría cambiar de una Lista
Por supuesto, solo es necesario aplicarlo a métodos que son visibles externamente (es decir, métodos públicos). Yo personalmente uso interfaces incluso en código interno, pero como usted mismo puede cambiar todo el código si realiza cambios de última hora, no es estrictamente necesario.
IEnumerable debe intentar usar el tipo menos específico que se adapte a su propósito. IEnumerable es menos específico que IList. Utiliza IEnumerable cuando desea recorrer los elementos de una colección
IList IList implementa IEnumerable. Debe usar IList cuando necesite acceder por índice a su colección, agregar y eliminar elementos, etc.
List List implementa IList
Siempre es mejor usar el tipo base más bajo posible. Esto le da al implementador de su interfaz, o consumidor de su método, la oportunidad de usar lo que quiera detrás de escena.
Para las colecciones, debe intentar usar IEnumerable siempre que sea posible. Esto le da la mayor flexibilidad, pero no siempre es adecuado.
Si trabajas con un único método (o incluso en una única clase o ensamblaje en algunos casos) y nadie va a ver lo que estás haciendo, utiliza la plenitud de una lista. Pero si está interactuando con un código externo, como cuando devuelve una lista de un método, solo quiere declarar la interfaz sin vincularse necesariamente con una implementación específica, especialmente si no tiene control sobre quién comstack en su contra. codificar después Si comenzó con un tipo concreto y decidió cambiar a otro, incluso si utiliza la misma interfaz, va a romper el código de otra persona a menos que haya comenzado con una interfaz o tipo de base abstracta.
No creo que haya reglas duras y rápidas para este tipo de cosas, pero por lo general sigo la pauta de usar la forma más liviana posible hasta que sea absolutamente necesario.
Por ejemplo, supongamos que tiene una clase Person
y una clase Group
. Una instancia de Group
tiene muchas personas, por lo que una lista aquí tendría sentido. Cuando declaro que el objeto de la lista en el Group
I IList
un IList
y lo instanciaré como una List
.
public class Group { private IList people; public Group() { this.people = new List (); } }
Y, si ni siquiera necesita todo en IList
, siempre puede usar IEnumerable
también. Con comstackdores y procesadores modernos, no creo que haya realmente una diferencia de velocidad, por lo que esto es más una cuestión de estilo.
En general, es mejor utilizar el tipo de uso más general, en este caso IList o incluso mejor la interfaz IEnumerable, para que pueda cambiar la implementación convenientemente más adelante.
Sin embargo, en .NET 2.0, hay algo molesto: IList no tiene un método Sort () . Puede usar un adaptador suministrado en su lugar:
ArrayList.Adapter(list).Sort()
El objeto AList le permite crear una lista, agregarle elementos, eliminarla, actualizarla, indexarla, etc. La lista se usa siempre que desee una Lista genérica donde especifique el tipo de objeto y eso es todo.
IList por otro lado es una interfaz. Básicamente, si desea crear su propio tipo de lista, diga una clase de lista llamada Lista de libros, luego puede usar la interfaz para darle los métodos básicos y la estructura de su nueva clase. IList es para cuando quieres crear tu propia subclase especial que implemente Lista.
Otra diferencia es: IList es una interfaz y no se puede crear una instancia. La lista es una clase y se puede crear una instancia. Significa:
IList MyList = new IList (); List MyList = new List
En situaciones que generalmente encuentro, rara vez uso IList directamente.
Usualmente lo uso como argumento para un método
void ProcessArrayData(IList almostAnyTypeOfArray) { // Do some stuff with the IList array }
Esto me permitirá hacer un procesamiento genérico en casi cualquier matriz en .NET framework, a menos que use IEnumerable y no IList, lo que sucede algunas veces.
Realmente se reduce al tipo de funcionalidad que necesita. Sugeriría usar la clase List en la mayoría de los casos. IList es mejor para cuando necesita crear una matriz personalizada que podría tener algunas reglas muy específicas que le gustaría encapsular dentro de una colección para que no se repita, pero aún desea que .NET la reconozca como una lista.
Debería usar la interfaz solo si la necesita, por ejemplo, si su lista se transfiere a una implementación de IList que no sea List. Esto es cierto cuando, por ejemplo, utiliza NHibernate, que arroja ILists en un objeto de bolsa NHibernate cuando recupera datos.
Si List es la única implementación que alguna vez usará para una determinada colección, no dude en declararla como una implementación concreta de la Lista.