2012-03-23 12 views
5

En muchos de nuestros proyectos, he visto algunas clases personalizadas de colección/contenedor que contienen algún tipo de colección genérica, p. una clase List(of T).¿Cuándo debería usar IEnumerable y GetEnumerator?

Por lo general, tienen un método GetXXX que devuelve un IEnumerable de cualquier tipo que use la clase de colección personalizada para que la colección interna se pueda iterar utilizando un bucle foreach.

p. Ej.

public IEnumerable<UploadState> GetStates 
{ 
    get 
    { 
     return new List<UploadState>(m_states); 
    } 
} 

Mi pregunta es que si estas clases en lugar implementar la interfaz IEnumerable, y llamar a GetEnumerator en la misma lista.

¿Hay alguna manera preferida, o depende del desarrollador?

+1

¿Qué es el tipo de m_states? Sólo me preguntaba por qué se envuelve por 'nueva lista <>' 'y devuelve como IEnumerable <>' – sll

+0

http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator.aspx –

Respuesta

2

Si su clase es una clase de colección personalizada, entonces sí, debe implementar IEnumerable<T>. En este caso, una propiedad pública para la lista interna sería redundante.Imagínese una clase simple:

public class People : IEnumerable<Person> 
{ 
    List<Person> persons = new List<Person>(); 

    public IEnumerator<Person> GetEnumerator() 
    { 
     return persons.GetEnumerator(); 
    } 
} 

Pero si la clase no puede actuar como una colección a continuación proporcionan una pública IEnumerable propiedad de sus elementos:

public class Flight 
{ 
    List<Person> passengers = new List<Person>(); 

    public IEnumerable<Person> Passengers 
    { 
     get { return passengers; } 
    } 
} 

De todos modos, siempre es responsabilidad del desarrollador para elegir la derecha diseño.

+0

Gracias Balazs Tihany, ¿puedo hacer una pregunta tonta sobre su ejemplo, ¿por qué se aplica a partir IEnumerable y no IEnumberble? No estoy seguro. – bobbo

+0

¿Por qué querrías? 'IEnumerable ' es genérico y seguro para tipos. 'IEnumerable' es para .NET 1.1 o tipos anónimos. Si solo implementa la interfaz 'IEnumerable', tendría que convertir los elementos de la lista a su tipo. –

2

lo haría de esa manera:

public IEnumerable<UploadState> GetStates 
{ 
    get 
    { 
     foreach (var state in m_states) { 
      yield return state; 
     } 
    } 
} 

Es más limpio, los usuarios no reciben una lista en la que no deberían (podrían echarlo a un List<T> después de todo) y usted don' Necesito crear un objeto List<T>.

EDIT: He entendido mal la pregunta. Creo que si la clase pretende ser una colección, debería implementar IEnumerable<T>.

+0

creo esto no se ha preguntado aquí, por lo que puede ser un comentario, no una respuesta, pero de todos modos tiene sentido desde el punto de vista de refactorización – sll

0

Debe derivar sus clases de recopilación personalizadas según una de las clases en el espacio de nombres System.Collections.ObjectModel. Ya contienen implementaciones de IEnumerable<T> y las interfaces no genéricas IEnumerable.

1

Considere que en su ejemplo de código se ha creado una nueva lista . No sé qué es m_states, pero si se trata de una colección de tipos de valores, crea un clon de la lista original. De esta forma, la lista de retorno se puede manipular a partir de los elementos Agregar/Eliminar/Actualizar de la persona que llama. sin afectando los datos originales.

Si m_states son los tipos de referencia, esto todavía crea una nueva lista que puede ser nuevamente manipulada por la persona que llama Añadir/Eliminar/No elementos de actualización (que es una referencia!) Sin afectar los datos originales.

¿Qué pasa con IEnumerable<T>, es sólo una forma de hacer un tipo de devolución genérica, y no hacer un fuerte acoplamiento al tipo List<T>.

+0

m_states es un tipo de referencia. Se declara como private List m_states = new List (); Pensé que la devolución del método no podría ser manipulada debido a la devolución de un IEnumerable , no una lista ? – bobbo

+0

@bobbo: seguro ** puede **, si selecciona un elemento de devolución de colección y cambia su propiedad, cambia la propiedad del elemento ** original **, ya que este es un tipo * de referencia *. – Tigran

+0

OK, eso tiene sentido. Sin embargo, su oración "Si m_states son tipos de referencia, esto aún crea una nueva lista que puede ser manipulada nuevamente por el llamador Agregar/Eliminar/Sin elementos de actualización (¡es una referencia!) Sin afectar los datos originales". es confuso. ¿Quiere decir que se ha agregado la nueva lista devuelta y que los elementos se pueden eliminar pero no hay actualizaciones? Pensé que debido a que devolvía ienumerable, puedes modificar los elementos en la lista, es decir, cambiar una propiedad como dijiste, pero no puedes agregar y eliminar elementos en la lista. ¿Es eso correcto? – bobbo

0

Creo que si su clase recientemente implementada solo se comporta de la misma manera que una lista, no hay necesidad de implementarla. Si necesita algún tipo de lógica personalizada, depende de lo que quiera hacer; puede heredar la lista o puede implementar IEnumerable. Simplemente depende de lo que se logrará.

Cuestiones relacionadas