2012-09-19 23 views
17

Me estoy poniendo en práctica IListSource que requiere un método GetList() con la siguiente firma:Convertir de IList <T> a no genérica IList

IList GetList() 

estoy usando NET Framework 2 y estoy con ganas de volver un objeto que implementa IList de la siguiente manera:

public System.Collections.IList GetList() 
{ 
    return this._mydata; // Implements IList<MyDataRow>    
} 

pero me da un error de compilación diciendo: Cannot implicitly convert type MyData to System.Collections.IList.

Si creo un nuevo lista del tipo List<MyDataRow>, pueble y devuelva este objeto de lista, entonces funciona. En otras palabras, esto funciona:

public System.Collections.IList GetList() 
{ 
    List<MyDataRow> list = new List<MyDataRow>(); 
    foreach (MyDataRow row in this._mydata) 
    { 
     list.Add(row); 
    } 
    return list; 
} 

Pero parece muy ineficiente a tener que volver a crear la lista sólo para obtener de tipo IList<T> a IList. ¿Por qué es que puedo devolver un List<MyDataRow>' from 'GetList(), pero no un IList<MyDataRow>? ¿Alguien sabe de alguna manera para devolver el IList<MyDataRow> sin volver a llenar una nueva lista?

ACTUALIZACIÓN:

La variable _mydata miembro se ha declarado:

private MyData _mydata; 

Y MyData se declara:

public class MyData : IList<MyDataRow> 
{ 
    .... 
} 
+0

¿Cuál es el tipo declarado del campo '_mydata' ? –

+1

@NicoleCalinoiu: Según el mensaje de error que recibe, es 'MyData'. – Heinzi

Respuesta

14

¿Por qué es que puedo devolver un List<MyDataRow> de GetList(), pero no un IList<MyDataRow>

Esto se debe a List<T> implementa IList, IList<T> no se puede convertir a IList son 2 interfaces separadas. Así que para responder a su pregunta:

¿Alguien sabe de alguna forma para devolver el IList<MyDataRow> sin volver a llenar una nueva lista?

Si el tipo concreto implementa IList (que List<T> hace) entonces se puede convertir explícitamente que, por ejemplo,

return (IList)this.mydata; 

actualización

En base a su actualización, tendrá que actualizar MyData para implementar IList de lo contrario no tiene más remedio que volver una nueva colección que qué ponerlo en práctica.

Alternativamente, si MyData es de hecho una lista genérica entonces sugeriría usted tiene que herede de List<T>, de esa manera se consigue mucho más la compatibilidad flexibilidad & fuera de la caja, por ejemplo,

class MyData : List<MyDataRow> 
{ 
} 
+0

Eso explica el problema, pero no proporciona una solución: myData es del tipo IList , todavía necesitaría llamar a .ToList() y quiere evitar eso. –

+0

@Baboon si 'myData' es del tipo' IList ', pero el tipo concreto es' List ', entonces todo lo que se necesita es un molde explícito. – James

+1

Gracias, James, por tu respuesta detallada. Voy a darle el crédito porque la sugerencia de heredar de la lista , en lugar de encapsular un miembro de la lista en mi clase como lo estaba haciendo, era la solución más simple a mi problema. Gracias por la ayuda. – BruceHill

4

La clase MyData necesidad de aplicar el IList junto con la versión genérica IList<T>.

class MyData : IList<MyDataRow>, IList 
{ 
} 
+0

+1. Me tomé la libertad de corregir el nombre de clase. (Según el mensaje de error del OP, la clase en sí es MyData, no MyDataRow). – Heinzi

+0

Gracias, entonces también funciona :) – Xharze

2

Si fuera posible convertir un IList<T> en un IList directamente, se puede devolver una lista que podría (por ejemplo) ser "contaminado" con T objetos no a través de su método Add(object).

+0

Su segundo párrafo llega al quid de la cuestión, pero el primero parece un poco apagado - el error de compilación ocurre precisamente porque 'IList ' no * se deriva de 'IList'. – shambulator

+0

Excelente punto. Enmendado en consecuencia, y gracias por la corrección. Estás absolutamente en lo correcto. –

3

IList<T> no extiende IList, porque no es razonable esperar que cada implementación de la versión genérica ofrezca el mismo contrato que el no genérico. Si se extendió IList, alguien podría tomar el valor devuelto desde GetList y razonablemente esperar llamar, p. Add(DateTime.Now), o Add(Thread.CurrentThread). Eso es lo que IList promete.

Esa es la razón por la copia de su lista a un List<T> obras - List<T> implementa ambas interfaces y tiros cuando su (implementado explícitamente) IList métodos se denominan con los tipos de parámetros inadecuados.

Si puede salirse con la suya devolviendo IEnumerable, hágalo en su lugar. Si puede devolver IList<MyDataRow>, haga eso. Si realmente necesita un retorno no genérico IList, implemente la interfaz y maneje los valores que no sean MyDataRow de manera apropiada.

+0

+1 para señalar los peligros de implementar 'IList' junto con' IList ' –

3

Cualquiera de aplicar IList en su clase de colección de datos o crear un adaptador, que se envuelve IList<T> e implementa IList:

public sealed class NonGenericList<T> : IList 
{ 
    private readonly IList<T> _wrappedList; 

    public NonGenericList(IList<T> wrappedList) 
    { 
     if(wrappedList == null) throw new ArgumentNullException("wrappedList"); 

     _wrappedList = wrappedList; 
    } 

    public int Add(object value) 
    { 
     _wrappedList.Add((T)value); 
     return _wrappedList.Count - 1; 
    } 

    public void Clear() 
    { 
     _wrappedList.Clear(); 
    } 

    public bool Contains(object value) 
    { 
     return _wrappedList.Contains((T)value); 
    } 

    public int IndexOf(object value) 
    { 
     return _wrappedList.IndexOf((T)value); 
    } 

    public void Insert(int index, object value) 
    { 
     _wrappedList.Insert(index, (T)value); 
    } 

    public bool IsFixedSize 
    { 
     get { return false; } 
    } 

    public bool IsReadOnly 
    { 
     get { return _wrappedList.IsReadOnly; } 
    } 

    public void Remove(object value) 
    { 
     _wrappedList.Remove((T)value); 
    } 

    public void RemoveAt(int index) 
    { 
     _wrappedList.RemoveAt(index); 
    } 

    public object this[int index] 
    { 
     get { return _wrappedList[index]; } 
     set { _wrappedList[index] = (T)value; } 
    } 

    public void CopyTo(Array array, int index) 
    { 
     _wrappedList.CopyTo((T[])array, index); 
    } 

    public int Count 
    { 
     get { return _wrappedList.Count; } 
    } 

    public bool IsSynchronized 
    { 
     get { return false; } 
    } 

    public object SyncRoot 
    { 
     get { return this; } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return _wrappedList.GetEnumerator(); 
    } 
} 

Uso:

public System.Collections.IList GetList() 
{ 
    return new NonGenericList<MyDataRow>(this._mydata); 
}