Question

Consider the following code that doesn't compile:

class WhyNot
{
    private Action _doSomething;
    public bool ThisOrThat;

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

I understand that this doesnt work because methods dont intrisically have a type, whereas delegates do, so an explicit cast must be made.

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

What I dont follow is why then does a standard if statement succeed in casting these where the ternary operator fails?

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

Why the difference between the operators?

Was it helpful?

Solution

Why explicit cast is required in Conditional operator

_doSomething = ThisOrThat ?  DoThis : DoThat; 

From this answer from Jon Skeet:

as the expression. What's the type of that? What delegate type should the method groups be converted to? The compiler has no way of knowing. If you cast one of the operands, the compiler can check that the other can be converted though

For your question:

Why it is allowed in if statement

You are doing a simple assignment where left hand side is Action and the right hand side is a method group. There exists implicit conversion

See Assignment Operator(=) C#

The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result. The operands must be of the same type (or the right-hand operand must be implicitly convertible to the type of the left-hand operand)

OTHER TIPS

Ternary operators infer the type of the result based on the types of the true and false conditions. The compiler does not account for the assignment operator ahead of the ternary operator when inferring the type.

When you attempt to compile your ternary statement it infers that the result type of the ternary operator is a method group, which fails to be assignable as a variable because methods have no type. This has nothing to do with the simple assignment ahead of your ternary operator: the failure is strictly in the ternary statement resulting in two method groups versus two delegates.

In an if statement, you're using a simple equality operator =. Thus the compiler infers the implicitly converted type of method group to delegate for you and so it basically becomes Action = (Action)method which succeeds.

Ultimately it's about the ternary operator's behavior and being unable to determine a type for two method groups. Are they delegates? If so, which delegates? It has no way of knowing, thus you must tell it what delegate to use by explicitly casting.

The relevant C# language spec entries:

7.12 Conditional Operator

7.13.1 Simple Assignment

6.1.4 Implicit Reference Conversions

This has nothing to do with if statements or assignment operators. The problem is entirely in the ternary conditional. From the docs:

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

If X and Y are the same type, then this is the type of the conditional expression. Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not
from Y to X, then Y is the type of the conditional expression.
Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not
from X to Y, then X is the type of the conditional expression.
Otherwise, no expression type can be determined, and a compile-time error occurs.

When you're trying to assign the method directly, it can be cast implicitly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top