我有一种情况,我有某种Item
和Collection
类的非泛型和泛型实现,其中集合必须包含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?)
答案 0 :(得分:2)
问题是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>)
”的类型参数。尝试明确指定类型参数。
答案 1 :(得分:2)
问题是,对于IEnumerable<T>
的不同值,类型会多次实现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();
无法知道它是Any
还是IEnumerable<int>
上的IEnumerable<string>
。
在您的情况下MyList<T>
实施IEnumerable<Item>
和IEnumerable<Item<T>>
。它不知道使用哪一个。
通过不依赖于泛型参数推断并明确指定类型,您可以解决该问题。 new MyList<int>().Any<Item<int>>();
编译得很好。 new MyList<int>().Any<Item>();
也可以。