2010-08-02 21 views
6

Gdy używam pętli foreach w języku C#, wydaje się, że nie jest wykonywane sprawdzanie typu czasu kompilacji, jeśli typ elementu jest typem interfejsu.Dlaczego foreach pomija czas kompilacji sprawdzania typów interfejsów?

E.g.

class SomeClass {} 
interface SomeInterface {} 

IEnumerable<SomeClass> stuff; 
foreach(SomeInterface obj in stuff) { // This compiles - why!? 
} 

to chętnie skompilować i spowodować wyjątek w czasie wykonywania, gdy jest jasne, w czasie kompilacji to nie ma sensu. Jeśli zmienić typ elementu z SomeInterface do innej klasy, a następnie kompilacji typu sprawdziany przywrócone:

IEnumerable<SomeClass> stuff; 
foreach(Random obj in stuff) { // This doesn't compile - good! 
} 

Dlaczego nie ma kompilacji typu kontroli czasu, gdy typ elementu jest interfejs?

(Dzieje się tak z .NET 3.5 SP1 w Visual Studio 2008)

+0

Tak, zastanawiałem się (i zostałem ukąszony) w tej samej rzeczy. Czekamy na odpowiedzi od tych, którzy wiedzą! – Eyvind

Odpowiedz

8

nie jest jasne, w czasie kompilacji, czy kolejna część programu, może w innym projekcie, posiada:

class SomeOtherClass : SomeClass, ISomeInterface 
{ 
    public static IEnumerable<SomeClass> GetSomeStuff() 
    { 
     for(int i = 0; i<10; ++i) 
     yield return new SomeOtherClass(i); 
    } 
} 

Teraz środowisko wykonawcze sprawdza SUCCEEDS.

Jeśli oznaczysz SomeClass jako sealed, nie będzie to możliwe, i znowu będzie można dowiedzieć się podczas kompilacji, że rzutowanie nigdy nie zadziała.

+0

To, co mówisz, jest poprawne. Jestem zaskoczony, że C# stosuje to podejście z "foreach", ponieważ sprawia, że ​​język jest niespójny. Wywołania metod nie mają na przykład takiego samego zachowania. – pauldoo

+0

+1 PERFECT odpowiedź. Nie myślałem o tym wcześniej. –

+0

To nie jest niespójne, to takie samo zachowanie jak casting, rozważ: foreach (SomeClass obj in stuff) ((ISomeInterface) obj) .SomeInterfaceMethod(); ' –