Does the ternary “?: operator” have a bug in C#?

2019-07-21 11:50发布

问题:

Why can not I run the following code ?

    static int num = 0;
    static void Main(string[] args)
    {
        (num == 0) ? inc() : dec();
    }
    public static void inc()
    {
        num++; 
    }
    public static void dec()
    {
        num--;
    }

Why doesn't C# allow me to use the ternary "?:" operator to check a condition and then run a method accordingly without the need to return any value? Equivalently to this:

            if (num == 0) inc();
            else dec();

I am not sure if the same rule is applied in other languages, e.g., Java, C++, etc...

回答1:

Jon Skeet's answer is perfectly documenting that C# intentionally went a different route than C++. It is difficult to say why, but I will try because I believe that that question deserves an answer, too.

C# shares a lot of syntax with C++ and with Java. In this case, the Java way was chosen. This concerns both the inability to write 2 + 2; as a standalone statement, as well as requiring that ternary operator returns a value.

I believe that both of these decisions have a lot to do with elimination of inaccessible code. The + operator in 2 + 2 can be optimized away and therefore if it serves any purpose in the code, that purpose is unreliably served! Static analysis (compilation error or warning) should ideally tell you that there seems to be a semantic problem in such a case and force you to delete or rewrite the inaccessible code.

So, expressions are no longer always statements, and the C grammar needs to be redefined for Java/C#, with expressions always returning values and statements never returning values.

Now ?: and if-else differ primarily in one being an expression and one being a statement, at least in their typical uses. So the redefined grammar simply chose to ban void ternaries and recommend if-else for that purpose.



回答2:

why can not I run the following code ?

Because you're trying to violate the language specification. The operands of the conditional operator (section 7.14 in the C# 4 spec) have to be expressions - and an invocation of a method with a return type of void is explicitly "only valid in the context of a statement-expression" (see section 7.1 of the C# 4 spec).

The purpose of the conditional operator is to provide an expression which is the result of evaluating one of two expressions based on a condition. It's not to execute one of two actions based on a condition. Just use an if statement.

Likewise the conditional operator does not form a valid statement on its own, any more than various other operators do:

a + b; // Invalid
x = a + b; // Valid, assignment expression can be an expression-statement

Explicitly from section 8.6 of the spec:

Not all expressions are permitted as statements. In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded) are not permitted as statements.



回答3:

Because Ternary operator assigns value based on a boolean expression. Its basic C# spec. If your methods are void return type then best is to use if - else or switch case.

int a = true ? 0 : 1; //Always works

true ? 0 : 1; //This will never work.

Or you example modified a little.

static int num = 0;

static void Main(string[] args)
{
    num = (num == 0) ? inc(num) : dec(num);
}

public static int inc(int lnum)
{
    return lnum + 1;
}

public static int dec(int lnum)
{
    return lnum - 1;
}


回答4:

The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.

It does not act the way you have described in your question. Here are more bytes on the ternary operator

http://msdn.microsoft.com/en-us/library/ty67wk28%28v=vs.80%29.aspx



回答5:

But it will work when used this way:

static int num = 0;
static void Main(string[] args)
{
    num = (num == 0) ? inc(num) : dec(num);
}
public static int inc(int number)
{
    return number + 1;
}
public static int dec(int number)
{
    return number - 1;
}