2010-03-19 12 views
8

Una de las estructuras de datos en mi proyecto actual requiere que almacene listas de varios tipos (String, int, float, etc.). Necesito ser capaz de almacenar dinámicamente cualquier cantidad de listas sin saber qué tipos serán.Lista de listas de diferentes tipos

Intenté almacenar cada lista como object, pero me encontré con problemas al tratar de volver al tipo apropiado (seguía reconociendo todo como List<String>).

Por ejemplo:

List<object> myLists = new List<object>(); 

public static void Main(string args[]) 
{ 
    // Create some lists... 

    // Populate the lists... 

    // Add the lists to myLists... 

    for (int i = 0; i < myLists.Count; i++) 
    { 
     Console.WriteLine("{0} elements in list {1}", GetNumElements(i), i); 
    } 
} 

public int GetNumElements(int index) 
{ 
    object o = myLists[index]; 

    if (o is List<int>) 
     return (o as List<int>).Count; 

    if (o is List<String>)     // <-- Always true!? 
     return (o as List<String>).Count; // <-- Returning 0 for non-String Lists 

    return -1; 
} 

estoy haciendo algo mal? ¿Hay una mejor manera de almacenar una lista de listas de varios tipos, o hay una mejor manera de determinar si algo es una lista de cierto tipo?

+0

¿Puedes publicar un programa mínimo pero completo que demuestre tu problema? – dtb

Respuesta

10

El tipo List<T> hereda de la interfaz no genérica IList. Dado que todos los valores del tipo myList están vinculados a intsance de List<T>, puede usarlos como el IList no genérico. Así que usted puede utilizar eso para simplificar en gran medida la lógica

public int GetNumElements(int index) { 
    object o = myLists[index]; 
    var l = o as IList; 
    return l.Count; 
} 

O, alternativamente, ya que usted sabe que todos los valores almacenados en myList habrá una versión encuadernada de List<T>, utilice IList como el tipo de lugar de object.

List<IList> myLists = new List<IList>(); 
... 
public int GetNumElements(int index) { 
    return myList[index].Count; 
} 
+0

Esto funciona hasta que tenga que manipular las listas o cuando tenga que recuperar un elemento de la lista después de haberlo insertado en la lista maestra. ¿Hay alguna manera fácil de decir qué tipo es un 'IList'? – themarshal

+0

@themarshal no no realmente. La única forma de comprobar realmente es usar el operador 'as' para convertir los tipos soportados y manipularlos. – JaredPar

+0

Finalmente me imaginé una manera de hacer un seguimiento del tipo de lista tal como se estaba insertando.La razón por la que todo se siguió leyendo como una lista de cadenas era porque cuando estaba creando listas basadas en el tipo, el tipo "Entero" generaba erróneamente una lista . Oops! – themarshal

2

Me doy cuenta de que este es un viejo, pero .NET 4 nos dio otra forma de evitar esto. ¿Qué sucede si quiere una Lista donde X es otra Lista, y y es cualquier tipo?

En otras palabras, una Lista> puede intentar el objeto, pero siempre estaría tratando de devolver algo a su tipo original, como se indica anteriormente.

Por lo tanto, este es un escenario raro donde se puede utilizar el nuevo tipo de datos dinámicos. Por supuesto, le permite romper la seguridad del tipo, pero en este caso, como siempre vamos a tratar con una lista de algún tipo, es justo decir que tendrá una propiedad ".Count".

Así que algo como:

var myMainList = new List<List<dynamic>>(); 
var myInnerList1 = new List<string> { "A", "B", "C" }; 
var myInnerList2 = new List<int> { 1, 2, 3, 4, 5 }; 
myMainList.Add(myInnerList1); 
myMainList.Add(myInnerList2); 

// when we come to try and read the number of values in the list.. 
Console.WriteLine("inner list 1 : {0}", myMainList[0].Count); 
Console.WriteLine("inner list 2 : {0}", myMainList[1].Count); 

Así, utilizando dinámica nos permite dejar caer el tipo de comprobaciones de seguridad. Muchos desarrolladores están en contra del uso de la dinámica. De hecho, decidí buscar activamente algo relacionado con una lista de listas de diferentes tipos, y vine aquí. Entonces agregué mi propia solución a mi problema. en realidad se está utilizando como una lista de datos de prueba, donde una lista externa contiene una lista de nombres de parámetros y una lista de valores de la colección para usar en las pruebas. Estos son diferentes por parámetro, y no quería volver constantemente del objeto a los tipos que conozco durante la creación del código fuente. Encontré que esta es una solución conveniente.

+0

¡su código ni siquiera se compila! – Arvand

Cuestiones relacionadas