2009-03-10 8 views
42

próbuję wykonać następującą obsadąObsada otrzymała obiekt do listy <object> lub IEnumerable <object>

private void MyMethod(object myObject) 
{ 
    if(myObject is IEnumerable) 
    { 
     List<object> collection = (List<object>)myObject; 
     ... do something 
    } 
    else 
    { 
     ... do something 
    } 
} 

Ale zawsze skończyć z następującym excepction:

Nie można rzutować obiektu typu ' System.Collections.Generic.List 1[MySpecificType]' to type 'System.Collections.Generic.List 1 [System.Object] '

Naprawdę potrzebuję tego do działania, ponieważ ta metoda musi być bardzo ogólna, aby otrzymywać pojedyncze obiekty i kolekcje obu nieokreślonych typów.

Czy to możliwe, czy jest inny sposób na osiągnięcie tego.

Dziękuję.

Odpowiedz

50

C# 4 będzie mieć kowariantna i kontrawariantny parametrów szablonu, ale do tego czasu trzeba coś zrobić nongeneric jak

IList collection = (IList)myObject; 
+0

Dziękuję. To zrobiło to. –

+1

@ Sergio, Należy sprawdzić, czy myObject implementuje IList zamiast IEnumerable przed rzutowaniem, jeśli chcesz uniknąć ryzyka błędów w czasie wykonywania. Wiele wbudowanych kolekcji implementuje IEnumerable, ale nie IList (np. Dictionary <>, HashSet <>, Hashtable, Queue, Stack etc). – LukeH

+0

@Luke: Jeśli jest to lista (co jest implikowane przez pytanie), wdroży IList. – erikkallen

2

Jak o

List<object> collection = new List<object>((IEnumerable)myObject); 
46

Nie można rzutować IEnumerable <T> do listy <T>.

Ale można tego dokonać za pomocą LINQ:

var result = ((IEnumerable)myObject).Cast<object>().ToList(); 
+0

Ten również działa. Dziękuję Ci. –

+2

To także tworzy nową listę, a nie rzutuje oryginalną. –

6

Czy rzeczywiście potrzebujemy więcej informacji niż zwykły IEnumerable daje? Wystarczy rzucić to i używać z nim foreach. Mam do czynienia z dokładnie taką samą sytuacją w niektórych bitach buforów protokołów i odkryłem, że przesyłanie do IEnumerable (lub IList, aby uzyskać do niej dostęp, podobnie jak lista) działa bardzo dobrze.

9

Problem polega na tym, że próbujesz upcast na bogatszy obiekt. Wystarczy dodać elementy do nowej listy:

if (myObject is IEnumerable) 
{ 
    List<object> list = new List<object>(); 
    var enumerator = ((IEnumerable) myObject).GetEnumerator(); 
    while (enumerator.MoveNext()) 
    { 
     list.Add(enumerator.Current); 
    } 
} 
+0

czy to działa? –

0

Ten kod pracował dla mnie

List<Object> collection = new List<Object>((IEnumerable<Object>)myObject); 
1

dołączyć do zabawy ...

private void TestBench() 
    { 
     // An object to test 
     string[] stringEnumerable = new string[] { "Easy", "as", "Pi" }; 

     ObjectListFromUnknown(stringEnumerable); 
    } 

    private void ObjectListFromUnknown(object o) 
    { 
     if (typeof(IEnumerable<object>).IsAssignableFrom(o.GetType())) 
     { 
      List<object> listO = ((IEnumerable<object>)o).ToList(); 
      // Test it 
      foreach (var v in listO) 
      { 
       Console.WriteLine(v); 
      } 
     } 
    } 
0

trzeba wpisać rzutuj używając operatora jako w ten sposób.

private void MyMethod(object myObject) 
{ 
if(myObject is IEnumerable) 
{ 
    List<object> collection = myObject as(List<object>); 
    ... do something 
} 
else 
{ 
    ... do something 
} 
}  
Powiązane problemy