2010-11-15 108 views
0

在一個非常基礎的學習練習中,我使用LinkedList,並且在需要返回最後一個元素時,我錯誤地使用Last()方法代替Last屬性,然後我開始懷疑。C# - 重載擴展方法

此方法是IEnumerable的擴展方法,所以如果它沒有被重載(Visual Studio + Resharper向我顯示此方法的基本IEnumerable擴展方法簽名),那將是非常低效的。

LinkedList MSDN page將大多數擴展方法指定爲「重載」。但我不確定它是什麼意思(單擊一個方法鏈接顯示基本方法的解釋),爲什麼Visual Studio + Resharper沒有顯示給我。

謝謝。

+0

如何尋找與反射器產生的代碼? – CodesInChaos 2010-11-15 21:10:39

+0

好的,我會盡力去做,明天更新(家裏沒有VS)。 – Evgeny 2010-11-15 21:18:35

+0

你不需要Visual Studio來使用.NET Reflector。 – StriplingWarrior 2010-11-15 21:32:57

回答

7

一個容易犯的錯誤是混淆加載超過。當MSDN頁面說方法被重載時,這意味着有多個版本的方法具有不同的參數。

您不能覆蓋擴展方法,因爲它們是靜態的。

+0

謝謝,我明白了。我認爲這意味着有一個對LinkedList更具體的重載。 – Evgeny 2010-11-15 21:20:42

+1

那麼,Last()和其他Linq擴展的邏輯實際上會進行一些類型的詢問,但我認爲這是針對索引類型(List,Array)的,因爲將索引類型視爲索引類型會更快,而不是遍歷它。對於LinkedList,不知道。您可以創建一個專門用於LinkedList的擴展方法Last();這樣你可以像對待大多數其他集合一樣對待它,但是當編譯器知道具體類型時會獲得更好的性能。 – KeithS 2010-11-15 21:50:02

2

你不能在技術上「覆蓋」擴展方法,因爲它們是靜態的。但是,如果類或接口上的某個方法與擴展方法具有相同的簽名,那麼編譯器將優先於擴展方法上的類或接口方法。所以通常情況下,以下行:

list.LastOrDefault() 

...實際上會被編譯爲:

Enumerable.LastOrDefault(list); 

但在下面的代碼:

public class LinkedList2<T> : LinkedList<T>{ 
    public T LastOrDefault() { 
     return Last.Value; 
    } 
} 
... 
var list = new LinkedList2<int>(); 
list.LastOrDefault(); 

編譯器實際上是要調用LinkedList2.LastOrDefault()而不是Enumerable.LastOrDefault<T>(this IEnumerable<T>)

因爲鏈表不具有Last()LastOrDefault()方法,但是,你最終會調用非常低效Enumerable.Last()