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循环,查询理解语法( selectwhere等)和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 } 

(编辑:答案在最初格式化的问题的上下文中确实有意义。编辑的问题使我的回答过时)