【问题标题】:Why can't I pass a List<List<Foo>> to an IEnumerable<IEnumerable<Foo>>为什么我不能将 List<List<Foo>> 传递给 IEnumerable<IEnumerable<Foo>>
【发布时间】:2012-01-25 10:09:59
【问题描述】:

此代码生成两个编译时错误:

private void DoSomething()
{
    List<List<Foo>> myFoos = GetFoos();

    UseFoos(myFoos);
}

private void UseFoos(IEnumerable<IEnumerable<Foo>>)
{

}

The best overloaded method match for 'NameSpace.Class.UseFoos(System.Collections.Generic.IEnumerable&lt;System.Collections.Generic.IEnumerable&lt;Foo&gt;&gt;)' has some invalid arguments

Argument 1: cannot convert from 'System.Collections.Generic.List&lt;System.Collections.Generic.List&lt;Foo&gt;&gt;' to 'System.Collections.Generic.IEnumerable&lt;System.Collections.Generic.IEnumerable&lt;Foo&gt;&gt;'

投射到IEnumberable&lt;List&lt;Foo&gt;&gt; 不是问题。强制转换失败类型的内部 List 组件有什么不同?

【问题讨论】:

标签: c# generics .net-3.5


【解决方案1】:

编辑:我刚刚意识到我还没有真正回答如何解决这个限制的问题。幸运的是,这很容易:

UseFoos(myFoos.Cast<IEnumerable<Foo>>());

该代码在 C# 4 下编译良好(当您为 UseFoos 参数指定名称时),它为接口和委托引入了泛型协变和逆变

作为一个更简单的示例,这在 C# 4 中有效,但在 C# 3 中无效:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

请注意,即使在 C# 4 中,类也不是一成不变的,所以这不起作用:

// This won't work
List<string> strings = new List<string>();
List<object> objects = strings;

...即使是接口,也只有在安全的情况下才支持:

// This won't work either
IList<string> strings = new List<string>();
IList<object> objects = strings;

接口(或委托)必须声明类型参数本身的变化,因此如果您查看 .NET 4 documentation for IEnumerable&lt;T&gt;,您会看到它被声明为

public interface IEnumerable<out T>

其中out 声明了T 中的协方差。

Eric Lippert 在他的covariance and contravariance 博客类别中有更多关于此的

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多