I have the following ASP.NET Web Api 2 action with a ternary if return:
[HttpDelete]
public IHttpActionResult Delete()
{
bool deleted;
// ...
return deleted ? this.Ok() : this.NotFound();
}
I receive a
Type of conditional expression cannot be determined because there is no implicit conversion between 'System.Web.Http.Results.OkResult' and 'System.Web.Http.Results.NotFoundResult'
when they both implement IHttpActionResult
.
However if I remove the ternary if, the compiler is happy:
if (deleted)
{
return this.Ok();
}
return this.NotFound();
Why is this?
You need to explicitly cast the result to IHttpActionResult
:
return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
Edit:
As for Grants question:
Why does Sam's second block of code work without explicitly casting to IHttpActionResult, just out of curiosity? Is this something particular to the conditional ?: operator?
Lets create a simple demonstration. Assume the following code:
public interface IFoo { }
public class B : IFoo { }
public class C : IFoo { }
And then the following:
public class A
{
IFoo F(bool b)
{
return b ? (IFoo) new B() : new C();
}
}
Lets see how the compiler de-compiles the ternary operator:
private IFoo F(bool b)
{
IFoo arg_13_0;
if (!b)
{
IFoo foo = new C();
arg_13_0 = foo;
}
else
{
arg_13_0 = new B();
}
return arg_13_0;
}
The explicit cast is enough for the compiler to infer that the variable should be of type IFoo
and hence satisfy our whole if-else
. That is why it is enough for us to "hint" the compiler only once of our type cast.
@dcastro has referenced the exact part of the language specification which determines the control of the type, see that for text-book definition.
In a ternary expression A? B : C
, there must be a reference conversion (e.g., from a base type to a derived type or vice-versa) from either B to C or C to B.
You expected the compiler to find the most derived common ancestor of the two types (which is IHttpActionResult
) - the compiler doesn't do that.
As a general rule of thumb, the type of the result of any expression must be contained within the expression itself. I.e., bool? dog : cat
cannot return an animal
because no variable of type animal
is part of the expression.
From the C# Language Specification section 7.14 Conditional Operator:
The second and third operands, x and y, of the ?: operator control the type of the conditional expression.
- If x has type X and y has type Y then
- If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression
- If an implicit conversion (§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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With