对 C# 的扩展方法重载解析感到困惑
Confused about C#'s extension method overload resolution
考虑以下代码:
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 + " ");
}
}
}
尝试 System.Linq.Enumerable.Take(source, 5)
而不是 Take(source, 5)
以强制使用原始 "Take" 函数或将您自己的 "Take" 重命名为其他东西 "Takef" 例如避免此类问题。
因为正如 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.
考虑以下代码:
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 + " ");
}
}
}
尝试 System.Linq.Enumerable.Take(source, 5)
而不是 Take(source, 5)
以强制使用原始 "Take" 函数或将您自己的 "Take" 重命名为其他东西 "Takef" 例如避免此类问题。
因为正如 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.