LINQ 中 AsEnumerable() 的内部实现

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

我有两个问题:

问题 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;

请帮助我理解,先谢谢您。

c# linq covariance contravariance
1个回答
3
投票
  1. 已知输入参数的类型为

    IEnumerable<TSource>
    。为什么需要投射任何东西?将对象转换为
    TSource
    类型不会有任何效果,因为它们已经保证是该类型(或更派生的类型)。

  2. 您无法将

    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
    
  3. 再次强调,

    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" };
    
    
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.