【问题标题】:Does LINQ "Query Syntax" Support Duck Typing?LINQ“查询语法”是否支持 Duck Typing?
【发布时间】:2013-08-07 21:20:44
【问题描述】:

关于 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 的查询语法!

好的,这里发生了什么?查询语法是否使用鸭子类型?当我自己试一试时,果然可行,而且似乎证明了这完全是关于鸭子类型的,而不是 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) 文档可能在哪里?或者任何合理的文件?

【问题讨论】:

    标签: c# .net linq duck-typing linq-query-syntax


    【解决方案1】:

    在 C# 中有一些特性,编译器会进行结构类型匹配而不是名义类型匹配。示例包括foreach 循环、查询理解语法(selectwhere 等)和await/async。对于所有这些特性,编译器实际上只是在寻找具有特定名称的方法,而不是特定的接口或类。

    这些功能与特定接口无关的原因是尽可能将语言与 .NET 框架实现分离。我想这会被认为是鸭子打字的一种形式。

    Eric Lippert 更彻底地解释了该功能和推理here

    我注意到MSDN documentation 在这些功能方面经常是错误的或不完整的。

    【讨论】:

    【解决方案2】:

    您缺少的是 List&lt;T&gt; 实现 IEnumerable&lt;T&gt;。因此,“我一直认为这种语法仅限于在 IEnumerable 上运行”在技术上是正确的,尽管方式有限。 IQueryable 也实现了 IEnumerable 以及 IList 和数组。因此,您可以针对任何实现 IEnumerable 的东西执行 linq 查询。

    由于Joker&lt;&gt; 没有实现IEnumerable&lt;&gt;,您的查询尝试将失败。 Select&lt;&gt;()Where&lt;&gt;()等扩展方法是围绕IEnumerable&lt;&gt;构建的。所以,如果你想从oof中选择,你只需要更新你对Joker&lt;&gt;的定义

    public class Joker<T> : IEnumerable<T>
    {
      // (actually implement IEnumerable<T> functionality
    }
    

    (编辑:在原始格式问题的上下文中,答案确实有意义。编辑后的问题使我的回答过时了)

    【讨论】:

    • 编辑了我的帖子 - 代码在没有 IEnumerable 参与的情况下运行。去图吧。
    • 哇,怎么样。也许编译器在运行时获得了超级反射,只是将from a in oof 转换为“为传入的类型查找Select 扩展方法,它最终可以工作?绝对没想到会这样。令人着迷。
    • 没有(运行时)反射......只是普通的旧“鸭子打字”。阅读我链接的维基百科文章。 :)
    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 2022-10-18
    • 2015-08-17
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多