繁体   English   中英

C# 什么时候得到 Action<..> 参数的这种“类似 SFINAE”的重载解析,它叫什么?

[英]When did C# get this “SFINAE-like” overload resolution of Action<..> parameters, and what is it called?

考虑以下代码,其中 C# 可以根据提供的隐式类型 Action<T>来消除重载的歧义,其中 T 是基于操作代码的 [互斥] 类型有效性派生的。

我很惊喜,意识到我已经“不假思索地依赖这种方便的行为”有一段时间了,尽管它要求编译器检查 Action 中的代码以及有效的目标站点类型。 通常必须先解析类型,然后才能在目标表达式中使用它。

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

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 中运行并生成以下 output:

string action
False
int action
True

C# 规范在匿名 Function 转换中涵盖了这一点。

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

在该部分中,它说匿名 function F可以转换为D委托类型,前提是:

如果F的主体是一个表达式,并且D具有void返回类型或FasyncD具有返回类型Task ,则当F的每个参数被赋予D中相应参数的类型时, F的主体是允许作为 statement_expression 的有效表达式 (wrt Expressions )。

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

当编译器在重载决议期间考虑适用的 function 成员时,根本不考虑采取Action<int>的重载,因为没有(隐式)转换为Action<int>

从这适用于所有匿名函数的事实来看,此功能可能并不新鲜。 它可能与delegate (...) {... }一样古老。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM