Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional operator doesn't work with two types that inherit the same base type

How come the conditional operator (?:) doesn't work when used with two types that inherit from a single base type?

The example I have is:

ActionResult foo = (someCondition)? 
                      RedirectToAction("Foo","Bar") :
                      Redirect(someUrl);

Where the long form works fine:

ActionResult foo;

if(someCondition)
{
  foo = RedirectToAction("Foo","Bar");
}
else
{
  foo = Redirect(someUrl);
}

Both return types, RedirectToRouteResult and RedirectResult, inherit from ActionResult.

like image 914
Jamie Dixon Avatar asked Jun 09 '12 19:06

Jamie Dixon


People also ask

What are the two types of conditional operators?

There are three conditional operators: && the logical AND operator. || the logical OR operator. ?: the ternary operator.

Does conditional operator take two operands?

The conditional operator (? :) is a ternary operator (it takes three operands).

How does a conditional operator work?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

What is difference between if-else and conditional operator?

The conditional operator is kind of similar to the if-else statement as it does follow the same algorithm as of if-else statement but the conditional operator takes less space and helps to write the if-else statements in the shortest way possible.


2 Answers

How come the conditional operator (?:) doesn't work when used with two types that inherit from a single base type?

The type of the conditional expression has to be either the type of the second operand or the type of the third operand, as per the language specification. The compiler doesn't try to find a common base type, or another type that both operands can be converted to. The use of the expression doesn't affect how its type is determined - so the variable assignment is irrelevant here.

As for why the language is defined like this - it makes it considerably simpler to specify, implement, test and predict. This is fairly common in language design - keeping the language simple is usually a better bet in the long run, even if it makes it slightly more awkward in some specific situations.

See section 7.14 of the C# 4 spec for more details.

Casting either the second or third operand to the type that you actually want for the conditional expression is the way to fix the problem. Note that another situation this often comes up in is nullable types:

// Invalid
int? a = SomeCondition ? null : 10;

// All valid
int? a = SomeCondition ? (int?) null : 10;
int? b = SomeCondition ? default(int?) : 10;
int? c = SomeCondition ? null : (int?) 10;
like image 66
Jon Skeet Avatar answered Oct 17 '22 04:10

Jon Skeet


The conditional operator cannot determine the resultant type from its components, which may be either RedirectToRouteResult or RedirectResult. In order to resolve this, you should explicitly cast either (or both) of the components to the base type:

ActionResult foo = (someCondition) ? 
                   (ActionResult)RedirectToAction("Foo","Bar") :
                   Redirect(someUrl);
like image 38
Douglas Avatar answered Oct 17 '22 05:10

Douglas