关于LINQ查询语法......
var foo = new List<int> { 1, 2 };
var boo = from n in foo
where n > 1
select n;
......我一直以为这个语法是limited to operating on IEnumerable。或者至少在我了解IQueryable之前。也许IObservable也是如此。但我最近注意到query syntax is based on duck typing的建议。在我发现一个致力于LINQ to Tasks的网站之前,这个故事看起来并不十分令人信服。 LINQ to Tasks看起来完全依赖duck typing查询语法!
好的,这里发生了什么?查询语法是否使用duck typing?当我自己尝试一下时,确实这有效并且似乎证明了所有关于鸭子打字,而不是IEnumerable:
public class Joker<T>
{
public T Item;
public Joker(T item)
{
Item = item;
}
}
public static class JokerHelp
{
public static T2 Select<T,T2>(this Joker<T> joke, Func<T,T2> call)
{
return call(joke.Item);
}
}
var oof = new Joker<int>(5);
int foo = from a in oof
select a;
如果鸭子打字是查询语法的工作方式,那么显然就是这种情况,哪里可能是关于此的官方(MSDN)文档?或者任何合理的文件?
答案 0 :(得分:7)
C#中有一些功能,编译器进行结构类型匹配而不是名义类型匹配。示例包括foreach
循环,查询理解语法(select
,where
等)和await
/ async
。对于所有这些功能,编译器实际上只是在寻找具有特定名称的方法,而不是特定的接口或类。
这些功能与特定接口无关的原因是尽可能地将语言与.NET框架实现分离。我想这可以被认为是鸭子打字的一种形式。
Eric Lippert更彻底地解释了这一功能和推理here。
我注意到MSDN documentation对于这些功能经常是错误的或不完整的。
答案 1 :(得分:4)
您遗失的是List<T>
实施IEnumerable<T>
。因此,“我一直认为这种语法限于在IEnumerable上运行”在技术上是正确的,尽管是以有限的方式。 IQueryable
同时实现IEnumerable
,以及IList
和数组。因此,您可以对实现IEnumerable
的任何内容执行linq查询。
由于Joker<>
未实现IEnumerable<>
,您的查询尝试将失败。 Select<>()
,Where<>()
等扩展方法围绕IEnumerable<>
构建。因此,如果您想从oof
中进行选择,只需更新Joker<>
public class Joker<T> : IEnumerable<T>
{
// (actually implement IEnumerable<T> functionality
}
(编辑:答案在最初格式化的问题的上下文中确实有意义。编辑的问题使我的回答过时了)