繁体   English   中英

无法在从实现IEnumerable的类派生的类上编译LINQ扩展方法<out T>

[英]Can't compile LINQ extension methods on classes that derive from a class implementing IEnumerable<out T>

我遇到的情况是,我有某种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?)

问题是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>)的类型参数。 尝试显式指定类型参数。

问题是,该类型实现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(); 不知道它是在IEnumerable<int>还是IEnumerable<string>上调用Any

在您的情况下, MyList<T>实现IEnumerable<Item>IEnumerable<Item<T>> 它不知道要使用哪个。

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

暂无
暂无

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

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