类型为IEnumerable的参数 >接受清单 >虽然IEnumerable)>不?

问题描述 投票:2回答:1

我上课了

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);

无法从'System.Collections.Generic.List <(int,System.Collections.Generic.List)>'转换为'System.Collections.Generic.IEnumerable <(int,System.Collections.Generic.IEnumerable)>'

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>)>

c# .net generics
1个回答
4
投票

它与covariance and contravariance有关。

IEnumerable<out T>是协变的,所以你可以指定一个更加派生的T类型,一切都会很好=> IEnumerable<Base> b = new List<DerivedFromBase>();

但在你的情况下IEnumerable<(int, IEnumerable<string>)>IEnumerable<ValueTuple<int, IEnumerable<string>>>相同,因为ValueTuple<int, List<string>>不是来自ValueTuple<int, IEnumerable<string>>you的衍生类型,所以不能那样使用它。

感谢@JeppeStigNielsen的更新

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

© www.soinside.com 2019 - 2024. All rights reserved.