代码之家  ›  专栏  ›  技术社区  ›  user2864740

C#什么时候获得这种“类似SFINAE”的重载操作解决方案<..>参数,它叫什么?

  •  0
  • user2864740  · 技术社区  · 3 年前

    考虑以下代码,其中C#可以根据 隐式类型的操作<T> 这是提供的,其中T是基于 论行为代码的[互斥]类型有效性

    我很惊喜,意识到我已经“毫无思想地依赖这种方便的行为”一段时间了,尽管它要求编译器检查动作中的代码以及有效的目标站点类型。通常必须解析类型 之前 它用于目标表达式中。

    这种行为是何时引入的?此类型推断的正确名称是什么?有哪些限制和已知的边缘情况?哪些文档链接(或规范中的部分)涵盖了该行为?

    static void WithAction(Action<string> s) {
        Console.WriteLine("string action");
        s("string");
    }
    
    static void WithAction(Action<int> i) {
        Console.WriteLine("int action");
        i(1);
    }
    
    void Main()
    {
        // Compiler has to INFER that this is an Action<string>
        // where the target type must be in {Action<string>, Action<int>}
        // (int does not have a Length property)
        WithAction(s => Console.WriteLine(s.Length == 1));
    
        // Ditto, except compiler infers Action<int>.
        // (there is no string == int operator overload)
        WithAction(i => Console.WriteLine(i == 1));
    
        // compiler error
        // CS0121 The call is ambiguous between the following methods or properties:
        // 'UserQuery.WithAction(Action<string>)' and 'UserQuery.WithAction(Action<int>)'
        // (there is both int == int and string == string!)
        // WithAction(z => Console.WriteLine(z == z));
    }
    

    该代码在LINQPad 5中运行,并生成以下输出:

    string action
    False
    int action
    True
    
    0 回复  |  直到 3 年前
        1
  •  2
  •   Sweeper    3 年前

    C规范在 Anonymous Function Conversions

    匿名函数包括旧的lambda表达式 delegate (...) { ... } 语法。

    在那一节中,它说匿名函数 F 可以转换为委托类型 D 提供:

    如果主体 F 是表达式,并且 D 有一个 void 返回类型或 F async D 具有返回类型 Task ,则当 F 中相应参数的类型 D ,主体 F 是有效表达式(wrt Expressions )这将被允许作为statement\u表达式。

    从本质上讲,关键是转换只有在“主体 F 是有效的(语句)表达式“。如果 s int ,则, Console.WriteLine(s.Length == 1) 不是有效的语句表达式,因此没有转换。

    当编译器在重载解析期间考虑适用的函数成员时,重载 Action<int> 因为没有(隐式)转换到 操作(<);内部(>);

    从这适用于所有匿名函数的事实来看 可能 这不是什么新鲜事。它可能和 委托(…){…}