派生类上没有扩展方法'First'

sgm*_*ore 5 c# generics extension-methods

鉴于(非常简单)代码.

public class Class1 
{
}

public class Class2 : Class1
{
}

public class List1 : System.Collections.Generic.IEnumerable<Class1>
{
    public new System.Collections.Generic.IEnumerator<Class1> GetEnumerator()
    {
        yield return new Class1();            
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}


public class List2  : List1 , System.Collections.Generic.IEnumerable<Class2> 
{       
    public new System.Collections.Generic.IEnumerator<Class2> GetEnumerator()
    {
        yield return new Class2();              
    }  

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是代码

var l = new List2();
var first = l.First();
Run Code Online (Sandbox Code Playgroud)

不会编译,但会给出错误

'List2'不包含'First'的定义,也没有扩展方法'First'可以找到接受类型'List2'的第一个参数(你是否缺少using指令或汇编引用?)

如果List2不是从List1派生的,那么它编译好,这证明List2确实有一个有效的扩展方法.

这只是一个误导性错误的情况,问题是它有两个扩展方法,不知道选择哪一个?

如果是这样,为什么它不能像编译器使用方法重载解析那样告诉Class2更具体的版本?

jas*_*son 7

问题是,List2同时实现了IEnumerable<Class1>IEnumerable<Class2>,所以编译器不知道的Enumerable.First<Class1>Enumerable.First<Class2>打电话.实际上,T编译器无法找到最好的调用Enumerable.First<T>(l),因此它不会将任何泛型Enumerable.First<T>作为合格方法.因此,它现在只查找First使用单个参数命名的非泛型方法,该方法l可以隐式转换为,并且找不到任何方法.

你可以明确地说出来

var first = l.First<Class1>();
Run Code Online (Sandbox Code Playgroud)

要么

var first = l.First<Class2>();
Run Code Online (Sandbox Code Playgroud)

然后你没事.