3 回答

TA貢獻2041條經(jīng)驗 獲得超4個贊
我很驚訝這里似乎達成了這樣的共識,即默認非虛擬化是正確的處理方式。我要講的是柵欄的另一面-我認為是實用的。
大多數(shù)論據(jù)都像古老的“如果我們給你力量,你可能會傷害自己”這樣的論點讀給我聽。來自程序員嗎?
在我看來,像編碼員一樣,他不了解(或沒有足夠的時間)來設(shè)計自己的庫以進行繼承和/或可擴展性,是恰好產(chǎn)生了我可能需要修復(fù)或調(diào)整的庫的編碼員。覆蓋功能最有用的庫。
我不得不編寫丑陋,絕望的變通方法代碼(或放棄使用并推出自己的替代解決方案)的次數(shù),因為我無法覆蓋太多,遠遠超過了我被咬過的次數(shù)(例如在Java中),通過覆蓋設(shè)計者可能沒有考慮過的地方。
默認非虛擬使我的生活更加艱難。
更新: [正確地指出]我實際上沒有回答問題。所以-很抱歉遲到了....
我有點希望能夠?qū)懗鲆恍┫瘛?C#在默認情況下將方法實現(xiàn)為非虛擬的方法,因為做出了一個錯誤的決定,使程序?qū)Τ绦虻闹匾暢潭雀哂诔绦騿T”。(我認為,根據(jù)該問題的其他一些答案(例如性能(過早的優(yōu)化,有人嗎?)或保證類的行為),這在某種程度上是合理的。)
但是,我意識到我只是在陳述自己的觀點,而不是Stack Overflow想要的明確答案。當(dāng)然,我認為,在最高層次上,確定的(但無濟于事的)答案是:
默認情況下,它們是非虛擬的,因為語言設(shè)計者需要做出決定,而這正是他們選擇的。
現(xiàn)在我想他們做出這個決定的確切原因我們將永遠不會....哦,等等! 對話記錄!
因此,這里關(guān)于覆蓋API的危險以及顯式設(shè)計繼承的需求的答案和評論似乎在正確的軌道上,但是都缺少一個重要的時間方面:Anders的主要關(guān)注點在于維護類或API的隱式跨版本合同。而且我認為他實際上更關(guān)心的是允許.Net / C#平臺在代碼下進行更改,而不是關(guān)注平臺頂部的用戶代碼更改。(他的“務(wù)實”觀點與我完全相反,因為他是從另一側(cè)看的。)
(但是他們不能只是默認情況下選擇了虛函數(shù),然后在代碼庫中添加了“最終”字嗎?也許那是不完全一樣的。而且安德斯顯然比我聰明,所以我要撒謊。)

TA貢獻1863條經(jīng)驗 獲得超2個贊
總結(jié)一下別人說的話,有以下幾個原因:
1-在C#中,語法和語義上有很多東西直接來自C ++。C ++默認情況下不是虛擬的方法會影響C#。
2-默認情況下,將每個方法虛擬化是性能問題,因為每個方法調(diào)用都必須使用對象的虛擬表。而且,這極大地限制了即時編譯器內(nèi)聯(lián)方法和執(zhí)行其他類型的優(yōu)化的能力。
3-最重要的是,如果默認情況下方法不是虛擬的,則可以保證類的行為。當(dāng)它們默認為虛擬時(例如在Java中),您甚至無法保證簡單的getter方法會按預(yù)期進行,因為它可能會被覆蓋以在派生類中做任何事情(當(dāng)然,您可以并且應(yīng)該使方法和/或最終課程)。
正如Zifre所提到的,您可能會想知道為什么C#語言沒有更進一步,并且默認情況下將類密封。這是關(guān)于實現(xiàn)繼承問題的整個辯論的一部分,這是一個非常有趣的話題。
添加回答
舉報