2010-11-15 88 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()