【问题标题】:Why doesn't the C# ternary operator work with delegates?为什么 C# 三元运算符不能与委托一起使用?
【发布时间】:2014-12-09 17:52:42
【问题描述】:

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

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'

【问题讨论】:

    标签: c# delegates ternary-operator


    【解决方案1】:

    问题在于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 用于解释类型推断失败的原因,并且您可以使用强制转换而不是 new
    【解决方案2】:

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

    如果你自己为其中一个参数提供这个,它会起作用:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 2022-12-03
      • 2011-07-23
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多