2013-03-15 11 views
6
MonoBehavior[] list; // This is from Unity3d but think of it as Object, 
        // all classes inherit from it. 

Lista jest wypełniona wieloma rzeczami, niektóre to Alfa, z klasy Alfa, a inne pochodzą z innych klas.foreach na liście [C#]

foreach(Alpha a in list) // Alpha is a script. 
    a.doSomething(); 

byłem przy założeniu, że moja foreach będzie działać w ten sposób: Foreach Alpha skrypt znalazł się na liście coś zrobić, zignorować każdy inny komponent.

Myślę, że to jest problem z rzucaniem. Proszę pomóż mi lepiej zrozumieć obsadę/polimorfizm.

otrzymuję ten błąd podczas wykonywania: Nie można rzucać od typu źródła do typu docelowego

+0

Tak wiele dobrych odpowiedzi, dzięki. Wybieram najlepsze po jakimś myśleniu :) –

Odpowiedz

2

to w jaki sposób mogę to zrobić i wiem na pewno, że to skompilować w Unity3D. OfType nie jest w Unity nawiasem mówiąc, TypeOf jest ale jako taras.roshko powiedział, że używanie is jest lepsze.

MonoBehavior[] list; 

foreach(MonoBehavior current in list) // Search the whole list for MonoBehaviors. 
    if (current is Alpha)   // Check if current is an Alpha type. 
     current.doSomething();  // current is a valid Alpha type script. 

The foreach spróbuje przekonwertować wszystkie elementy na liście, a od Alpha to MonoBehavior ale MonoBehavior nie jest alfa nie można go uruchomić poprawnie. Sprawdza się więc, czy prąd jest alfą, a jeśli jest, użyj go w dowolny sposób.

0

swoje oświadczenie foreach spróbuje rzucić każdy obiekt w tam Alpha. Jeśli mają wspólną nadklasę, możesz jej użyć, w przeciwnym razie użyj klasy Object.

2

użycie OfType iteracyjne nad elementów określonego typu tylko

13

Można spróbować czegoś takiego:

foreach(Alpha a in list.Where(x => x is Alpha)) // Alpha is a script. 
    a.doSomething(); 
2

Jeśli chcesz pętli działać tylko na Alpha typów, trzeba przepisać jako następujące :

foreach (var item in list) 
{ 
    if (item is Alpha) 
    { 
    ((Alpha) item).doSomething(); 
    } 
} 

edytuj: Odpowiedź Maarten używa LINQ, który jest bardziej zwięzły, więc polecam ten.

+0

Lepszą decyzją byłoby użycie operatora "as" –

+0

Czy użycie słowa kluczowego 'is' jest efektywnie takie samo jak' if (a.GetType == TypeOf (Alpha) '? – Amicable

+2

"is" nie zawiedzie, jeśli a ma wartość null (zostanie ocenione na false), wywołanie "GetType" przy wartości null spowoduje wyjątek NullReferenceException, więc podejście "jest" jest lepsze, ale jeszcze lepiej jest użyć "jak" operator.Kolejnym krokiem jest użycie metody LINQ "OfType") –

11

Wychodzisz na polimorfizm w zły sposób: podczas gdy Alpha jest typem pochodnym, nie wszystkie inne obiekty na liście typu MonoBehavior są. Dlatego niektóre z nich zawiodą w niejawnym typie rzucanym przez foreach. Można użyć „OfType()” rozszerzenie, o ile jest ona dostępna w danym środowisku:

foreach(Alpha a in list.OfType<Alpha>()) 
0

Jeśli lista zawiera listę typu bazowego i jesteś po prostu biorąc każdy element i spróbuj pomyśleć, że jest typu Alpha niż jest to nielegalne spróbuj poniżej

foreach(Unity3d a in list) // Alpha is a script. 
    a.doSomething(); 

zakładając doSomething() jest defind w Unity3D