可以';t编译从实现IEnumerable<;输出T>;

本文关键字:lt 输出 IEnumerable gt 编译 可以 实现 | 更新日期: 2023-09-27 18:22:01

我有一种情况,我得到了某种ItemCollection类的非泛型和泛型实现,其中集合必须包含Items,泛型集合必须包含特定类型的泛型项。

public class Item { }
public class Item<T>: Item  {  }
public class MyList : IEnumerable<Item>  {  
    public IEnumerator<Item> GetEnumerator() { }
}
public class MyList<T> : MyList, IEnumerable<Item<T>>  { 
    public new IEnumerator<Item<T>> GetEnumerator() { }
}

问题是Linq扩展方法在列表的通用版本上不起作用:

// works
var test1 = new MyList().Any();
// intellisense understands this, but it won't compile
var test2 = new MyList<int>().Any();

这是使用.NET 4.5。我认为这与两个冲突接口IEnumerable<Item>IEnumerable<Item<T>>的存在有关。我所期望的是派生的优先。

为什么不编译,实现这样的东西的正确方法是什么,这样我就可以在集合类的非泛型和泛型版本中公开IEnumerable<T>接口?如果我只是从非通用版本中删除IEnumerable<Item>接口,一切都会很好,但当然,如果不通过其他非标准方法公开它,我就无法枚举它。

Error: MyList<T>' does not contain a definition for 'Any' and no extension method 'Any' accepting a first argument of type 'Item<T>' could be found (are you missing a using directive or an assembly reference?)

可以';t编译从实现IEnumerable<;输出T>;

问题是MyList<T>实现了两次IEnumerable<T>,因此编译器无法推断Enumerable.Any<TSource>的泛型参数的类型。

您必须明确指定要使用的T

var test2 = new MyList<int>().Any<Item>();
// or
var test2 = new MyList<int>().Any<Item<int>>();

不幸的是,错误消息并不能很好地传输这些信息。如果使用正常语法调用扩展方法,则消息非常清楚。

呼叫:

var test2 = Enumerable.Any(new MyList<int>());

结果:

无法根据用法推断方法"System.Linq.Enumerable.Any<TSource>(System.Collections.Generic.IEnumerable<TSource>)"的类型参数。请尝试显式指定类型参数。

问题是,对于T的不同值,该类型多次实现IEnumerable<T>。一个更简单的复制方法是:

public class Foo : IEnumerable<int>, IEnumerable<string>
{
    public IEnumerator<int> GetEnumerator()
    {
        throw new NotImplementedException();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

现在,代码new Foo().Any();不知道它是在IEnumerable<int>还是在IEnumerable<string>上调用Any

在您的案例中,MyList<T>实现了IEnumerable<Item>IEnumerable<Item<T>>。它不知道该用哪一个。

通过不依赖泛型参数推断并显式指定类型,可以解决该问题。new MyList<int>().Any<Item<int>>();编译得很好。CCD_ 23也会起作用。