C# 当所有表达式具有相同类型时,在一种情况下(而不是在另一种情况下)出现编译错误
我有一段代码: 方法如下:C# 当所有表达式具有相同类型时,在一种情况下(而不是在另一种情况下)出现编译错误,c#,linq,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 s
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;
}
由于select子句中表达式的类型相同,我希望它在两种情况下都能编译,或者在两种情况下都会失败
如果我使用方法语法而不是查询压缩和写入:
collection.Where(item => item.Id > 10).Select(item => item)
这也编译了
我的问题是这是一个编译器错误还是我遗漏了什么
编辑
我没有使用System.Linq,所以正常的选择和where方法不起作用,只有下面的方法
该代码是一项学术练习的一部分,旨在尝试扩展LINQ基于模式的方法重载解析。这些签名是故意的怪异/令人惊讶,其中包括一个投影,尽管我认为这通常是一个非常糟糕的主意
编辑
相关类的定义和select扩展方法
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{
}
如错误消息中所示 返回的值与方法签名的值不同 如果您阅读了错误消息,则表明它期望C,但得到B
return from item in collection
where item.Id > 10
select (c)item;
看起来你所缺少的只是从b到c的演员阵容。可能是使用.Select扩展方法,编译器可以自动执行此强制转换。我见过编译器根据返回类型使用正确的泛型方法。因此,不用说MyItem item=GenericMethodinput,可以说MyItem item=GenericMethodinput,编译器知道使用哪种类型。这就是查询表达式转换的全部内容。您可能希望了解C语言规范4.0 7.16.2或7.15.2 for C 3.0的更多详细信息,但简而言之,表达式如下:
from x in c
where f(x)
select x
翻译成
c.Where(x => f(x))
因此不会调用Enumerable.Select,结果将是IEnumerable而不是IEnumerable。编译器到底在抱怨什么。此代码所在的方法的签名是什么?你分配给它的变量是什么类型的?我理解用幽默和你喜欢的博客链接来增加趣味性的诱惑,但你的问题会被那些可以根据标题回答的人扫描,然后多年来,可能有同样问题的人会再次按标题扫描你的问题,或者一个完全无关的问题。你没有在帮助这些人。PS:您不太可能发现编译器错误,尤其是假设错误行为是发出错误消息时。大多数编译器错误都是默默地发出错误的代码。集合的定义是什么?@Oded我已经发布了定义。我不认为这对于更一般的问题很重要,即当所有表达式的类型都相同时,为什么它在实例中失败而不是在另一个实例中失败:您真的认为这可能是编译器错误吗?然后解释为什么方法语法中完全相同的代码确实返回方法签名的类型。selct方法确实返回C。如果你是正确的,那么为什么要选择新的B全部工作?阅读Konstantin Oznobihin的回答。我间接地问错误消息是否正确,那么表达式之间的区别是什么。你的答案没有解释什么会改变选择表达式的类型,并且会失败,因为它找不到匹配的选择方法。我在中找到它的部分是7.15.2 thoughyes,在C3.0中是7.15.2。我已经编辑了我的答案,以便更容易地找到规范的这一部分。一个有趣的选择是总是删除select。我觉得很奇怪,因为如果忽略where,select实际上是在7.15.2.3中执行的,在本例中,这会导致两个函数的返回类型不同cases@RuneFS:在正常情况下无需调用identity Select,但确保查询表达式的结果永远不是源对象本身仍然很重要,这就是为什么它在没有“where”时被称为where。我想说的是,最好避免像您这样的Select方法,而是使用单独的扩展方法,比如除了普通的Select之外的CONVERTOC。我完全同意,从编码角度来看,我所介绍的代码没有什么意义。然而,它是作为一项学术活动的一部分而产生的,这项学术活动故意试图写出怪异/令人惊讶的linq。尝试查看基于模式的方法过载的程度。决议可能会受到影响。我个人觉得很不幸,x中的from项目预选项目与x中的from项目不一致。。或者,true select与simply select不同。我觉得这一点也不奇怪
c.Where(x => f(x))