我有两个问题:
问题 1 背景: 在查看 Microsoft LINQ 中“AsEnumerable()”方法的实现时,我注意到:
public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
问题1: 我期望在这里进行某种类型的转换或其他操作,但它只是返回所传递的值。这是如何运作的 ?
问题 2/3 背景: 我一直在尝试理解协变、逆变和不变。我认为,我有一个模糊的理解,即“in”和“out”关键字决定将子类型分配给父类型时的多态行为。
问题2: 我从阅读中知道 IEnumerable 是协变的,而 List 是不变的,那么为什么这是不可能的:
List<char> content = "testString".AsEnumerable();
问题3:
如果 IList 实现 IEnumerable 那么为什么这是不可能的:
IEnumerable<char> content1 = "testString";
IList<char> content2 = content1;
请帮助我理解,先谢谢您。
已知输入参数的类型为
IEnumerable<TSource>
。为什么需要投射任何东西?将对象转换为 TSource
类型不会有任何效果,因为它们已经保证是该类型(或更派生的类型)。您无法将
IEnumerable<char>
类型的值分配给 List<char>
类型的变量。我认为你在这里想的是相反的; List<char>
源自 IEnumerable<char>
,而不是相反。这与 List<T>
不变无关。 IEnumerable<T>
是协变的(更准确地说,类型参数 T
是协变的),这给了我们这样的情况:
IEnumerable enumerable = Enumerable.Empty<string>(); // Allowed
IEnumerable<string> genericEnumerable = enumerable; // Not allowed
再次强调,
IList<char>
继承自IEnumerable<char>
,而不是相反。你可以这样做:
IList<char> content1 = "testString".ToList();
IEnumerable<char> content2 = content1;
恐怕你所要求的没有意义,而且与协方差无关。 IEnumerable<T>
是协变的事实意味着您可以这样做:
IEnumerable<object> asObject = new List<string>() { "test" };
但是
List<T>
是不变的,所以你不能这样做:
List<object> asObject = new List<string>() { "test" };