当所有表达式具有相同类型时,编译错误在一种情况下而不是另一种情况

时间:2011-09-30 09:08:36

标签: c# linq

我有一段代码:

方法如下:

public IEnumerable<c> Test(){
  var collection = new a();
  IEnumerable<c> bs = collection.Where(item => item.Id > 10).Select(item => item);
  return from item in collection
         where item.Id > 10
         select item;
}

(前两行编译好)

它无法编译并失败:

  

无法隐式将System.Collections.Generic.IEnumerable<Stackoverflow.b>类型转换为System.Collections.Generic.IEnumerable<Stackoverflow.c>

但是下面的代码编译得很好:

return from item in collection
       where item.Id > 10
       select new b(null);

因为select子句中表达式的类型是相同的,我希望它在两种情况下都能编译,或者两者都失败。

如果我使用方法语法而不是查询comprehesion并写:

collection.Where(item => item.Id > 10).Select(item => item)

太编译了

我的问题是“Is there something wrong with the universe”(这是编译器错误)还是我错过了什么?

修改

我没有using System.Linq所以正常选择和方法不在其中只有下面的那些 该代码是学术练习的一部分,旨在尝试和扩展LINQ基于模式的方法重载解析。签名是刻意的奇怪/令人惊讶的,其中包括一个投影,但我相信这通常是一个非常糟糕的主意。

修改

有问题的类的定义和选择扩展方法

public static class Enumerable {
    public static IEnumerable<c> Select(this IEnumerable<b> self, Func<b,b> selector){
        return null;
    }
}

public class a{
    public IEnumerable<b> Where(Predicate<a> predicate){
        return null;
    }
    public int Id { get; set; }
}

public class b{
}

public class c{
}

3 个答案:

答案 0 :(得分:6)

这就是查询表达式的翻译。您可能需要查看C#语言规范4.0 7.16.2(或C#3.0的7.15.2)以获取更多详细信息,但简而言之,表达式如下:


from x in c
where f(x)
select x

仅翻译为


c.Where(x => f(x))

所以你的Enumerable.Select不会被调用,你将获得IEnumerable&lt; b&gt;结果而不是IEnumerable&lt; c&gt;。正是编译器抱怨的是什么。

答案 1 :(得分:1)

正如错误消息所示。

您没有返回与方法签名相同的值。

如果您阅读错误消息,则表示它期望C但是得到B

答案 2 :(得分:0)

尝试

return from item in collection
    where item.Id > 10
    select (c)item;

似乎所有你缺少的是从b到c的演员阵容。可能是使用.Select扩展方法,编译器可以自动计算出这个转换。我已经看到编译器使用基于返回类型的正确泛型方法。因此,不是说MyItem item = GenericMethod<MyItem>(input)可以说MyItem item = GenericMethod(input)而是编译器知道要使用哪种类型。