6

If have the following statement:

return this.revision.HasValue ? this.revision : throw new InvalidOperationException();

I thought it would compile as the throw is breaking the normal flow and it shouldn't be a problem to not return a value but it does not build.

Is there a way to put right this statement or why is this not allowed?

Thanks.

EDIT: this.revision is int? and the method returns int.

EDIT 2: if I have this method

public int Test()
{
    throw new Exception();
}

The compiler does not complain about not returning a value, I expected the same thing from an inline if ... at least we know that can be done as it's already done in methods.

Ignacio Soler Garcia
  • 21,122
  • 31
  • 128
  • 207

5 Answers5

13

Converting comment to an answer:

From MSDN:

Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.

?: Operator

As int? cannot be converted to an exception, and throw is not an expression, hence the error within your code.

Ric
  • 12,855
  • 3
  • 30
  • 36
  • Again, I expected the compiler to be smart enough to realize that in this case the return value does not matter ... Check my edit – Ignacio Soler Garcia Nov 22 '13 at 10:45
  • but it's slightly different than a traditional if..else statement in that it the types have to match or be able to be converted for assignment. – Ric Nov 22 '13 at 10:46
  • 5
    "I expected the computer to violate it's programming and read my mind. Please help, internet." – Gusdor Nov 22 '13 at 10:47
  • 2
    @SoMoS: The compiler is smart but it has to follow rules and one rule is that the syntax must be valid. If you use a conditional operator the rules are strict. If you don't like it you have to use an `if-else`. – Tim Schmelter Nov 22 '13 at 10:48
  • 1
    @Ric: _"int? cannot be converted to an exception, hence the error within your code"_ Even if it could be converted to an exception the code would be invalid since `throw` is not an exception type, `throw` is disallowed in a conditional operator. – Tim Schmelter Nov 22 '13 at 10:49
  • 1
    _As int? cannot be converted to an exception_ -> wrong, it's not the cause at all. If the OP used an exception instead, it wouldn't work either. – ken2k Nov 22 '13 at 10:53
  • @ken2k Just pointing out the type mistmatch is all I was getting at. How would you have worded it? Also the quote from MSDN clearly illustrates that types must be the same or a conversion must exist. – Ric Nov 22 '13 at 10:54
  • 1
    @Ric: A conditional operator needs two [**expressions**](http://msdn.microsoft.com/en-us/library/ms173144(v=vs.110).aspx) and each expression must have the same type (or an implicit conversion exists). `throw` is a [**statement**](http://msdn.microsoft.com/en-us/library/ms173143(v=vs.110).aspx) not an expression. – Tim Schmelter Nov 22 '13 at 10:57
  • 2
    @Ric That's not a type mismatch, it's just `throw` is not an expression. – ken2k Nov 22 '13 at 10:57
3

I suppose the problem is in the fact that this.revision is a nullable type and InvalidOperationException() is a SystemException. You cannot have two different types in an if statement like:

return (a>b)? DateTime.Now : 2;

Please look here: http://msdn.microsoft.com/en-us/library/vstudio/ty67wk28.aspx

condition ? first_expression : second_expression;

The condition must evaluate to true or false. If condition is true, first_expression is evaluated and becomes the result. If condition is false, second_expression is evaluated and becomes the result. Only one of the two expressions is evaluated.

Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.

Christos
  • 53,228
  • 8
  • 76
  • 108
  • I expected the compiler to be smart enough to realize that in this case the return value does not matter ... – Ignacio Soler Garcia Nov 22 '13 at 10:44
  • @SoMoS the ternary operator requires the types to be the same or implicitly convertible http://msdn.microsoft.com/en-us/library/ty67wk28%28v=vs.110%29.aspx – Gusdor Nov 22 '13 at 10:46
2

It's because in a ternary expression, the latter two expressions act as a substitute to each other and their return value needs to be of same type or implicitly convertible to type of the variable being assigned.
Clearly, an Exception has different type than an int.

MSDN:

If condition is false, second_expression is evaluated and becomes the result.

Ganesh Jadhav
  • 2,830
  • 1
  • 20
  • 32
1

This is because the second operand of ?: needs to be an expression, not a throw statement.

so what you can do is-

public static T ThrowException<T>()
{
    throw new Exception();
}

and use it in your statement

return this.revision.HasValue ? this.revision :ThrowException<bool>();
Rui Jarimba
  • 11,166
  • 11
  • 56
  • 86
Microsoft DN
  • 9,706
  • 10
  • 51
  • 71
1

C# compiler could allow for that and it could do many more things than it does today. The problem is the cost of writing the feature and then supporting it. See Eric Gunnerson's blog post outlining the new feature decision process.

ya23
  • 14,226
  • 9
  • 46
  • 43