为什么C#三元运算符不能与代理一起使用?

Fox*_*xor 19 c# delegates ternary-operator

分支选择函数时,使用三元运算符选择函数可能是有意义的,但这是不可能的.为什么?

public class Demo {
    protected bool branch;
    protected void demo1 () {}
    protected void demo2 () {}
    public Action DoesntWork() {
        return branch ? demo1 : demo2;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器产生以下错误:

Cannot implicitly convert type `method group' to `System.Action'
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 24

问题是,这demo1不是一个简单的表达,它是一种方法.并且方法可以被覆盖,因此它实际上不是一个方法,它是一个方法组.请考虑以下示例:

public class Demo {
    protected bool branch;
    protected void demo1 (int) {}
    protected void demo1 () {}
    protected void demo2 () {}
    public Action DoesntWork() {
        return branch ? demo1 : demo2; //Error
        return demo1; //ok
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,demo1是否过载,应该使用哪两个版本中的哪一个?答案是通过使用使用函数的上下文来选择重载函数.

return demo1很明显,它期望的Action.

但在return branch? demo1 : demo2;上下文中并不那么容易.三元操作者首先尝试匹配的类型demo1与的demo2,但那是另一种方法组,所以没有帮助那里.编译器不会超越并失败.

解决方案是清除方法组中预期的类型:

return branch? new Action(demo1) : demo2;

return branch? (Action)demo1 : demo2;

Action d1 = demo1;
return branch? d1 : demo2;
Run Code Online (Sandbox Code Playgroud)

  • +1用于说明类型推断失败的原因,并且您可以使用强制转换而不是`new`。 (2认同)

Ree*_*sey 6

您必须显式创建适当类型的委托.通常,您可以使用demo1引用a System.Action,但这只是因为编译器可以根据用法推断出类型并为您创建委托.在这种情况下,编译器不知道System.Action在三元运算符中使用时应将您的方法转换为.

如果您自己提供这个参数甚至其中一个参数,它将起作用:

public Action DoesWork() 
{
    return branch ? demo1 : new Action(demo2);
}
Run Code Online (Sandbox Code Playgroud)

由于这会new Action为一个参数显式返回,因此编译器可以推断出另一个应该转换为适当的a System.Action,并且它将成功编译.