接口一个被我忽略的地方--接口重定向技术
習慣于用IDE生成接口方法了,右鍵點擊"Implement Interface",生成所有的接口方法聲明,還帶個Region多方便啊.
今天看<<CLR Vir C#>>時才了解到自己是知其然不知其所有然啊.
?實現接口方法很簡單,新手估計也都會,但怎么理解這個過程,不見得所有人都知道
class?Base?:?IDisposable
{?
????IDisposable?Members#region?IDisposable?Members
????public?void?Dispose()
????{
????????Console.WriteLine("Base's?Dispose");
????}
????#endregion
}
首先我們可以簡單的認為Base類里有個Dispose()的方法.這個方法跟是不是IDisposable的成員,先理解為沒有關系.當編譯這個類的時候,編譯器發現它實現了IDisposable接口,于是查找有沒有跟其成員IDisposable.Dispose()同名,參數和返回類型完全匹配,并且是public的,如果找到就在IVMap里指向這個方法的入口(我猜的,這地方具體見http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true)如果沒有就出個編譯錯誤.
如果找到的方法前面有virtual關鍵字,編譯器仍然認為是匹配的.如何沒有virtual關鍵字,編譯器默認的還會為其加上sealed.那么其子類是無法override的.如何想要override父類的Dispose()方法,最好是在Base中定義Dispose()時使用virtual.當然如果我們沒有權利改寫Base類,我們可以讓其子類同樣繼承自IDisposable,然后改寫方法.這點已經有很多人談論過了,估計大家基本都明白.不了解的可以gongle it!
Derived
class?Derived?:?Base,?IDisposable
{
????public?void?Dispose()
????{
????????Console.WriteLine("Derived's?Dispose");
????}
}
現在問題來了,我們是真的改寫了父類的Dispose()方法嗎?
測試一下:
Base c = new Derived();
c.Dispose();
結果你可以發現輸出的是: Base's Dispose.當時我覺得很奇怪,后來靜下來想想原來可以這么理解.
就如我開始理解接口實現過程一樣,對于上面的代碼我們可以直接忽略接口的存在,等效如下
class?Base?
{?
????public?void?Dispose()
????{
????????Console.WriteLine("Base's?Dispose");
????}
}
class?Derived?:?Base?
{
????public?void?Dispose()
????{
????????Console.WriteLine("Derived's?Dispose");
????}
}
這樣大家應該都知道為什么輸出是Base's Dispose,如果不知道可以去查看 "今天你多態了嗎"一文,說的很詳細了.
回過來看我們剛才的代碼,編譯的時候有個警告:?? 'Program.Derived.Dispose()' hides inherited member 'Program.Base.Dispose()'. Use the new keyword if hiding was intended.?
是不是把Dispose()看成只是類的方法更容易理解呢.只是通過接口調用的時候指向了這個方法的入口而已.
我以為如下實現Derived類會更好些,不會讓你產生誤解,以為Derived? override了Base類的Dispose()方法
顯示實現接口class?Derived?:?Base,?IDisposable
{
????void?IDisposable.Dispose()
????{
????????Console.WriteLine("Derived's?Dispose");
????}
}
對于如下代碼不要期待能輸出Derived's Dispose結果.當然如果CallDispose()傳入的參數類型是IDisposable,就當我沒說過
static void Main(string[] args)
{
??? Derived c = new Derived();
??? CallDispose(c);
}
private static void CallDispose(Base b)
{
??? b.Dispose();
}
要不然你得這樣
private static void CallDispose(Base b)
{
??? ((IDispose))b.Dispose();
}
但是你會覺得很別扭.當然 CallDispose(Base b)定義成這樣本身就是個不好的設計.
具體大家可以看看<<CLR Vir C#>>14章,我想對于你理解接口實現的整個過程會有莫大的幫助
轉載于:https://www.cnblogs.com/anders06/archive/2007/06/12/780719.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的接口一个被我忽略的地方--接口重定向技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS样式表的规划与组织
- 下一篇: 蘋果的秘密武器