【发布时间】:2020-04-27 15:20:53
【问题描述】:
考虑以下代码:
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 + " ");
}
}
我在IEnumerable<T> 上为Take(long) 提供了一个扩展名,该框架未提供该扩展名。该框架仅提供Take(int)。由于我使用 int 参数 (Take(5)) 调用它,我本来希望它使用框架版本,但它正在调用我的扩展。
我错过了什么吗?最接近的匹配显然是以int 作为参数的匹配,并且包含System.Linq,因此它应该在有效重载池中。事实上,如果我删除我的扩展,就会调用正确的框架函数。
编辑:将它们移动到不同的命名空间显示相同的问题:
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 + " ");
}
}
}
【问题讨论】:
-
通过阅读
linq.Take上的文档,您永远不需要从IEnumerable中提取超过20 亿个项目。因此,框架不提供.Take(long)的原因。 -
你试过用
5L而不是5来调用它吗? -
我认为因为你的扩展方法和调用者都在同一个命名空间中,所以那个会赢。暂时不记得具体的规则了。
-
@Sean,我调用
long版本的Take没有问题,这实际上是我的问题。 -
@Blindy 你的例子没有实际应用,会被认为是糟糕的设计。无论您是否征求意见,我都在指出您的示例中的错误。
标签: c# overloading overload-resolution