类型为IEnumerable <ienumerable <string>&gt;的参数接受List <list <string>&gt;而IEnumerable&lt;(int,IEnumerable <string>)&gt;没有按&#39;吨?

时间:2017-12-27 17:13:35

标签: c# .net generics

我有一个班级

public class Test
{
    public void M1(IEnumerable<IEnumerable<string>> p) { }
    public void M2(IEnumerable<(int, IEnumerable<string>)> p) { }
}
var t = new Test();

以下代码工作正常。

var d1 = new List<List<string>> { new List<string>{ "test" } };
t.M1(d1);

但是,以下代码会收到错误

var d2 = new List<(int, List<string>)> { (1, new List<string>{ "test" }) };
t.M2(d2);
  

无法转换为&#39; System.Collections.Generic.List&lt;(int,System.Collections.Generic.List)&gt;&#39; to&#39; System.Collections.Generic.IEnumerable&lt;(int,System.Collections.Generic.IEnumerable)&gt;&#39;

d2必须定义为

var d2 = new List<(int, IEnumerable<string>)> { (1, new List<string>{ "test" }) };

类型为IEnumerable<IEnumerable<string>>的参数接受List<List<string>>IEnumerable<(int, IEnumerable<string>)>不接受List<(int, List<string>)>

1 个答案:

答案 0 :(得分:4)

它与covariance and contravariance有关。

IEnumerable<out T>是协变的,因此您可以指定更多派生类型的T,所有这些都很好=&gt; IEnumerable<Base> b = new List<DerivedFromBase>();

但在您的情况下,IEnumerable<(int, IEnumerable<string>)>IEnumerable<ValueTuple<int, IEnumerable<string>>>相同,而ValueTuple<int, List<string>>不是来自ValueTuple<int, IEnumerable<string>>的派生类型,您无法以这种方式使用它。

感谢@JeppeStigNielsen

主要原因是因为协变从不与值类型一起使用,而C#7的新元组是值类型,而且ValueType<T1, T2>在T2中也不协变