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

时间:2014-10-14 19:56:38

标签: c# delegates ternary-operator

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

public class Demo {
    protected bool branch;
    protected void demo1 () {}
    protected void demo2 () {}
    public Action DoesntWork() {
        return branch ? demo1 : demo2;
    }
}

编译器产生以下错误:

Cannot implicitly convert type `method group' to `System.Action'

2 个答案:

答案 0 :(得分:21)

问题是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
    }
}

现在,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;

答案 1 :(得分:6)

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

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

public Action DoesWork() 
{
    return branch ? demo1 : new Action(demo2);
}

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