Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ中AsEnumerable()的内部实现_C#_Linq_Compiler Construction_Covariance_Contravariance - Fatal编程技术网

C# LINQ中AsEnumerable()的内部实现

C# LINQ中AsEnumerable()的内部实现,c#,linq,compiler-construction,covariance,contravariance,C#,Linq,Compiler Construction,Covariance,Contravariance,我有两个问题: 问题1背景: 当我看到Microsoft在LINQ中实现“AsEnumerable()”方法时,我注意到: public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source) { return source; } 公共静态IEnumerable AsEnumerable(此IEnumerable源) { 返回源; }

我有两个问题:

问题1背景: 当我看到Microsoft在LINQ中实现“AsEnumerable()”方法时,我注意到:

public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{ 
   return source;
} 
公共静态IEnumerable AsEnumerable(此IEnumerable源)
{ 
返回源;
} 
问题1: 我在这里期待某种类型的强制转换或其他东西,但它只是返回传递的值。这是怎么回事

问题2/3背景: 我一直在努力理解协方差、逆变换和不变量。我想,我对“in”和“out”关键字在将子类型指定给父类型时决定多态行为有一个模糊的理解

问题2: 我从阅读中了解到IEnumerable是协变的,List是不变的,那么为什么这不可能:

List<char> content = "testString".AsEnumerable();
IEnumerable<char> content1 = "testString";
IList<char> content2 = content1;
List content=“testString”.AsEnumerable();
问题3:
如果IList实现IEnumerable,那么为什么不可能:

List<char> content = "testString".AsEnumerable();
IEnumerable<char> content1 = "testString";
IList<char> content2 = content1;
IEnumerable content1=“testString”;
IList content2=content1;
请帮我理解,提前谢谢

  • 已知输入参数的类型为
    IEnumerable
    。为什么它需要投下任何东西?将对象强制转换为类型
    TSource
    不会有任何效果,因为它们已经被保证为该类型(或更派生的类型)

  • 不能将
    IEnumerable
    类型的值分配给
    List
    类型的变量。我想你的想法是相反的<代码>列表源自
    IEnumerable
    ,而不是反过来。这与
    List
    不变无关
    IEnumerable
    是协变的(更准确地说,类型参数
    T
    是协变的),这给了我们以下情况:

    IEnumerable enumerable = Enumerable.Empty<string>(); // Allowed
    IEnumerable<string> genericEnumerable = enumerable; // Not allowed
    
    IEnumerable enumerable=enumerable.Empty();//允许
    IEnumerable genericEnumerable=可枚举;//不准
    
  • 同样,
    IList
    继承自
    IEnumerable
    ,而不是相反。您可以这样做:

    IList<char> content1 = "testString".ToList();
    IEnumerable<char> content2 = content1;
    
    IList content1=“testString”.ToList();
    IEnumerable content2=content1;
    
    恐怕你所要求的毫无意义,而且与协方差无关。
    IEnumerable
    是协变的,这意味着您可以这样做:

    IEnumerable<object> asObject = new List<string>() { "test" };
    
    IEnumerable asObject=new List(){“test”};
    
    但是
    List
    是不变的,所以您不能这样做:

    List<object> asObject = new List<string>() { "test" };
    
    List asObject=new List(){“test”};
    

  • AsEnumerable()强制查询在其他LINQ提供程序(如LINQ to SQL或实体框架)中立即执行。它可能是为了完整性而添加到LINQ对象中的。我需要一些时间来消化它!作为对第一个答案的回应,我明白了,所以如果我可以直接将派生对象的值分配给父类型的实例,“AsEnumerable()”解决了什么问题?作为对第二个答案的回应,好的,那么为什么IEnumerable enumerable=(IEnumerable)enumerable.Empty();不可能?IEnumerable实现了IEnumerable,那么为什么编译器会抱怨呢?@RaM你又反过来想了
    IEnumerable
    实现了
    IEnumerable
    ,这意味着您可以将
    IEnumerable
    的实例分配给
    IEnumerable
    类型的变量,而不是相反。在您引用的示例中,编译器不知道该变量实际上是
    IEnumerable
    的实例。我对示例进行了编辑,希望能更清楚一点。至于AsEnumerable(),老实说,我也不太确定它的意义是什么。的备注部分指出,它可以用于“隐藏”其他LINQ方法的特殊实现,如
    Where
    Select
    ,但这对我来说似乎是一个奇怪的原理。也许我从来就不需要它。