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