我有一个班级
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>)>
?
答案 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中也不协变