2013-03-06 38 views
3

按照語言規範http://msdn.microsoft.com/en-us/library/bb383977.aspx什麼問題會有在允許覆蓋擴展在C#

您可以使用擴展方法來擴展一個類或接口,但不 覆蓋它們。將永遠不會調用具有相同名稱和簽名 作爲接口或類方法的擴展方法。在編譯時, 擴展方法的優先級總是低於類型本身定義的實例方法 。

我不明白的是爲什麼有這個限制嗎? 允許覆蓋擴展有什麼編程問題?

簡單的情況下研究

基類Object具有方法ToString(),它由缺省對象類型名稱返回到一個字符串。可以說,爲了所有的意圖和目的,它被設計爲被覆蓋。

默認情況下,Stream不提供對ToString的覆蓋,因爲它不知道將字節轉換爲字符串是否有意義。

但是,作爲解決方案的程序員,我知道如果轉換爲字符串,所有流都是有意義的。但是,我不想,或不能,從流類派生。所以,我想擴展ToString方法將流轉換爲字符串;像這樣:

public static String ToString(this Stream stream) 
{ 
    var memory = new MemoryStream(); //closable 
    var reader = new StreamReader(memory); 
    stream.Position = 0; 
    stream.CopyTo(memory); 
    memory.Position = 0; 
    return reader.ReadToEnd(); 
} 

但是,根據規範,這將永遠不會在運行時調用。但爲什麼在這種情況下對這種限制非常嚴格?由於Stream派生自Object,它是否應該表示默認情況下,應該默認覆蓋基本類型方法的任何擴展方法專門用於Stream

此外,有些情況下,簡單地命名它AsString將是沒有用的;即使用ToString作爲後備代表項目的WPF。

+1

這可能是可能的 - 但該功能不存在的原因是因爲,爲了解釋Eric Lippert,*沒有人實現它*。成本/收益沒有理由(尚)。 (更多討論請見http://blogs.msdn.com/b/ericlippert/archive/2009/06/22/why-doesn-t-c-implement-top-level-methods。aspx) – 2013-03-06 12:45:56

+0

如果您使用的是第三方庫,它使用Stream的派生類(虛構類XmlStream),它依賴於Stream.ToString()的默認行爲,該怎麼辦?既然您已經修改了該行爲,那麼第三方代碼的行爲是否與預期不同? – publicgk 2013-03-06 12:47:18

回答

4

擴展方法不在擴展對象的繼承層次結構中。

語言(和IDE)只是使這個完全獨立於類看起來像它是擴展類型的一部分。

爲了允許重寫,整個繼承模型和擴展機制需要改變 - 這是一個非常大的改變,可能是一個突破。

總之 - 這是一個功能,其實施成本將超過其實用性。