2010-08-02 80 views
6

當我在C#中使用foreach循環時,如果項類型是接口類型,則看起來沒有執行編譯時類型檢查。爲什麼foreach跳過對接口類型的編譯時類型檢查?

E.g.

class SomeClass {} 
interface SomeInterface {} 

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

這將高興地編譯並在運行時導致異常,當它在編譯時清楚這是沒有意義的。如果我改變從SomeInterface項目類型到另一個類,然後編譯時類型檢查恢復:

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

爲什麼沒有編譯時的類型檢查的項目類型是一個接口?

(這發生在Visual Studio .NET 2008 3.5 SP1)

+0

是的,我想知道(而且被咬了)同樣的事情。期待知道者的答案! – Eyvind 2010-08-02 15:44:28

回答

8

這是不是在編譯時是否該計劃的另一部分,可能在不同的項目中,有明確的:

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

現在運行時檢查成功。

如果您將SomeClass標記爲sealed那麼這是不可能的,並且在編譯時再次可能知道演員將無法工作。

+0

你說的是對的。我很驚訝C#採用這種方法與「foreach」,因爲它使語言不一致。例如,方法調用沒有這種相同的行爲。 – pauldoo 2010-08-02 15:58:37

+0

+1 PERFECT答案。以前沒有想過它。 – 2010-08-02 16:08:40

+0

這不是不一致的,它與cast相同的行爲,請考慮:'foreach(SomeClass obj in stuff)((ISomeInterface)obj).SomeInterfaceMethod();' – 2010-08-02 16:09:53