0

我有一种情况,我有某种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?)

4

2 回答 2

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();不知道它是调用AnyanIEnumerable<int>还是调用IEnumerable<string>.

在你的情况下MyList<T>实现IEnumerable<Item>IEnumerable<Item<T>>. 它不知道该使用哪一个。

通过不依赖泛型参数推断并明确指定类型,您可以解决该问题。 new MyList<int>().Any<Item<int>>();编译就好了。 new MyList<int>().Any<Item>();也可以。

于 2013-07-10T17:18:13.410 回答
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>)无法从用法中推断方法“ ”的类型参数。尝试明确指定类型参数。

于 2013-07-10T17:16:11.997 回答