【问题标题】:Difference between ternary (conditional) operator and if statement returning an Action三元(条件)运算符与返回 Action 的 if 语句之间的区别
【发布时间】:2013-12-18 16:23:52
【问题描述】:

考虑以下无法编译的代码:

class WhyNot
{
    private Action _doSomething;
    public bool ThisOrThat;

    public WhyNot()
    {
        _doSomething = ThisOrThat ?  DoThis : DoThat;   
    }
    private void DoThis()
    {}
    private void DoThat()
    {}
}

我知道这不起作用,因为methods dont intrisically have a type,而代表可以,所以explicit cast must be made

_doSomething = ThisOrThat ? (Action)DoThis : (Action)DoThat;    

我不明白的是,为什么标准 if 语句在三元运算符失败的情况下成功转换这些?

if (ThisOrThat)
    _doSomething = DoThis;
else
    _doSomething = DoThat;

为什么运营商之间有区别?

【问题讨论】:

  • 您确定 _doSomething 在 if 语句的情况下具有值吗?也许它是空的?
  • _doSomething = ThisOrThat ? (Action) DoThis : DoThat; 这也可以编译。你可能会看到this answer from Jon Skeet
  • @Habib 我在帖子中引用了那个答案,(必须进行明确的演员表)你可以做一侧或另一侧。只是不知道为什么 IF 能做到。
  • @paqogomez:我认为答案在 Jon 的回答中——"[The compiler] 没有使用您试图分配给变量的事实来计算条件表达式的类型"
  • 请注意,var foo = MethodName; 的分配有类似的问题 - 它无法确定 var 的类型。

标签: c# if-statement ternary-operator


【解决方案1】:

这与if 语句或赋值运算符无关。问题完全在于三元条件。来自文档:

?: 运算符的第二个和第三个操作数控制条件表达式的类型。设 X 和 Y 是第二个和第三个操作数的类型。那么,

如果 X 和 Y 是同一类型,那么这是条件表达式的类型。 否则,如果存在从 X 到 Y 的隐式转换(第 6.1 节),但不存在
从 Y 到 X,则 Y 是条件的类型 表达。
否则,如果存在从 Y 到 X 的隐式转换(第 6.1 节),但不存在
从 X 到 Y,那么 X 是条件的类型 表达式。
否则无法确定表达式类型,并出现编译时错误。

当您尝试直接分配方法时,它可以被隐式转换。

【讨论】:

    【解决方案2】:

    三元运算符根据真假条件的类型推断结果的类型。推断类型时,编译器不会在三元运算符之前考虑赋值运算符。

    当你试图编译你的三元语句时,它会推断出三元运算符的结果类型是一个方法组,它不能作为变量赋值,因为方法没有类型。这与三元运算符之前的简单赋值无关:失败严格在三元语句中,导致两个方法组与两个委托。

    if 语句中,您使用的是简单的相等运算符=。因此编译器会推断出隐式转换的方法组类型来为你委托,所以它基本上变成了Action = (Action)method,它成功了。

    最终它是关于三元运算符的行为并且无法确定两个方法组的类型。他们是代表吗?如果有,有哪些代表?它无法知道,因此您必须通过显式强制转换来告诉它要使用什么委托。

    相关的 C# 语言规范条目:

    7.12 Conditional Operator

    7.13.1 Simple Assignment

    6.1.4 Implicit Reference Conversions

    【讨论】:

      【解决方案3】:

      为什么在条件运算符中需要显式转换

      _doSomething = ThisOrThat ?  DoThis : DoThat; 
      

      来自 Jon Skeet 的 this answer

      作为表达式。那是什么类型的?应该使用什么委托类型 方法组转换为? 编译器没有办法 知道。如果您强制转换操作数之一,编译器可以检查 另一个可以转换虽然

      对于您的问题:

      为什么if 语句中允许使用它

      你正在做一个简单的赋值,左边是Action,右边是一个方法组。存在隐式转换

      Assignment Operator(=) C#

      赋值运算符 (=) 存储其右侧操作数的值 在由其左侧表示的存储位置、属性或索引器中 操作数并将值作为结果返回。操作数必须是 相同类型(或右手操作数必须是隐式的 可转换为左侧操作数的类型)

      【讨论】:

        猜你喜欢
        • 2011-04-22
        • 1970-01-01
        • 2011-05-10
        • 2013-05-17
        • 2012-09-17
        • 2017-11-19
        • 2012-02-12
        • 2017-10-20
        • 2021-09-18
        相关资源
        最近更新 更多