[英]Confused about C#'s extension method overload resolution
Consider the following code:考虑以下代码:
using System;
using System.Linq;
using System.Collections.Generic;
public static class Ex
{
public static IEnumerable<T> Take<T>(this IEnumerable<T> source, long cnt)
{
return source;
}
}
public class C
{
public static void Main()
{
foreach(var e in Enumerable.Range(0, 10).Take(5).ToArray())
Console.Write(e + " ");
}
}
I have an extension on IEnumerable<T>
for Take(long)
, which isn't provided by the framework.我在
IEnumerable<T>
上有一个Take(long)
的扩展,框架没有提供。 The framework only provides Take(int)
.该框架仅提供
Take(int)
。 And since I'm calling it with an int
parameter ( Take(5)
), I would have expected it to use the framework version, but it's calling my extension.而且由于我使用
int
参数( Take(5)
)调用它,我本来希望它使用框架版本,但它正在调用我的扩展。
Am I missing something?我错过了什么吗? The closest match would obviously be the one that takes
int
as a parameter, and System.Linq
is included so it should be in the pool of valid overloads.最接近的匹配显然是将
int
作为参数的匹配,并且System.Linq
包含在内,因此它应该在有效重载池中。 In fact if I delete my extension, the correct framework function is called.事实上,如果我删除我的扩展,就会调用正确的框架 function。
Edit: Moving them to different namespaces shows the same problem:编辑:将它们移动到不同的名称空间显示相同的问题:
using System;
using System.Linq;
using System.Collections.Generic;
namespace N1
{
public static class Ex
{
public static IEnumerable<T> Take<T>(this IEnumerable<T> source, long cnt)
{
return source;
}
}
}
namespace N2
{
using N1;
public class C
{
public static void Main()
{
foreach(var e in Enumerable.Range(0, 10).Take(5).ToArray())
Console.Write(e + " ");
}
}
}
Because as Eric Lippert puts it:因为正如 Eric Lippert 所说:
the fundamental rule by which one potential overload is judged to be better than another for a given call site: closer is always better than farther away.
对于给定的呼叫站点,判断一个潜在过载比另一个更好的基本规则:越近总是比越远越好。
Try System.Linq.Enumerable.Take(source, 5)
instead of just Take(source, 5)
to force using the original "Take" function or rename your own "Take" into somthing else "Takef" for example to avoid this kind of problems.尝试
System.Linq.Enumerable.Take(source, 5)
而不是Take(source, 5)
强制使用原始的“Take” function 或将您自己的“Take”重命名为其他“Takef”,例如以避免这种情况的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.