简体   繁体   English

为什么编译器选择IEnumerable超过IEnumerable <T>的重载?

[英]Why does the compiler choose overload with IEnumerable over IEnumerable<T>?

Consider the following two extension methods: 考虑以下两种扩展方法:

using System;
using System.Collections.Generic;
using System.Linq;

public static class Extensions
{
    public static bool Contains(this IEnumerable self, object obj)
    {
        foreach (object o in self)
        {
            if (Object.Equals(o, obj))
            {
                return true;
            }
        }
        return false;
    }

    public static bool ContainsEither<T>(this IEnumerable<T> self, T arg1, T arg2)
    {
        return self.Contains(arg1) || self.Contains(arg2);
    }
}

When I wrote my second method, I intended it to call the generic LINQ Enumerable.Contains<T> method (type arguments inferred from the usage). 当我编写第二个方法时,我打算调用泛型LINQ Enumerable.Contains<T>方法(从用法推断出类型参数)。 However, I found out that it is actually calling the first method (my custom Contains() extension method. When I comment out my Contains() method, the second method compiles fine, using the Enumerable.Contains<T>() method. 但是,我发现它实际上是在调用第一个方法(我的自定义Contains()扩展方法。当我注释掉我的Contains()方法时,第二个方法使用Enumerable.Contains<T>()方法编译得很好。

My question is, why does the compiler choose my Contains() method with non-generic IEnumerable argument over Enumerable.Contains<T>() with IEnumerable<T> argument? 我的问题是,为什么编译器选择带有非通用IEnumerable参数的Contains()方法而不是Enumerable.Contains<T>()IEnumerable<T>参数? I would expect it to choose Enumerable.Contains<T>() because IEnumerable<T> is more derived than IEnumerable . 我希望它选择Enumerable.Contains<T>()因为IEnumerable<T>IEnumerable派生更多。

My question is, why does the compiler choose my Contains() method with non-generic IEnumerable argument over Enumerable.Contains<T>() with IEnumerable<T> argument? 我的问题是,为什么编译器选择带有非通用IEnumerable参数的Contains()方法而不是Enumerable.Contains<T>()IEnumerable<T>参数?

Because it's found in the same namespace that contains the method calling it. 因为它位于包含调用它的方法的同一名称空间中。 Types declared within that namespace effectively have precedence over types declared in imported namespaces. 在该命名空间内声明的类型实际上优先于在导入的命名空间中声明的类型。

From the C# 5 specification, section 7.6.5.2: 从C#5规范,第7.6.5.2节:

The search for C proceeds as follows: 对C的搜索过程如下:

  • Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods: 从最近的封闭命名空间声明开始,继续每个封闭的命名空间声明,并以包含的编译单元结束,连续尝试查找一组候选扩展方法:
    • If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set. 如果给定的命名空间或编译单元直接包含具有合格扩展方法Mj的非泛型类型声明Ci,则这些扩展方法的集合是候选集。
    • If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set. 如果在给定命名空间或编译单元中使用命名空间指令导入的命名空间直接包含具有合格扩展方法Mj的非泛型类型声明Ci,则这些扩展方法的集合是候选集。
  • If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs. 如果在任何封闭的名称空间声明或编译单元中找不到候选集,则会发生编译时错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM