Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use operator ?? and throw new Exception()?

I have a number of methods doing next:

var result = command.ExecuteScalar() as Int32?; if(result.HasValue) {    return result.Value; } else {    throw new Exception(); // just an example, in my code I throw my own exception } 

I wish I could use operator ?? like this:

return command.ExecuteScalar() as Int32? ?? throw new Exception(); 

but it generates a compilation error.

Is it possible to rewrite my code or there is only one way to do that?

like image 412
abatishchev Avatar asked Nov 19 '09 11:11

abatishchev


People also ask

Can we throw exception in ternary operator?

You can't throw an exception in a ternary clause. Both options must return a value, which throw new Exception(); doesn't satisfy.

How to throw exception from one method to another in Java?

Using the Throws keyword Throws is a keyword used to indicate that this method could throw this type of exception. The caller has to handle the exception using a try-catch block or propagate the exception. We can throw either checked or unchecked exceptions.

Can new throw an exception C++?

Throwing exceptions from C++ constructors Since C++ constructors do not have a return type, it is not possible to use return codes. Therefore, the best practice is for constructors to throw an exception to signal failure. The throw statement can be used to throw an C++ exception and exit the constructor code.

What does throw new exception do?

"throw "and "throw new" Exception() In the above case, throws the original exception but resets the stack trace , destroying all stack trace information until your catch block. This means that, it excludes stack information from the point where you called "Throw ex" .


2 Answers

For C# 7

In C# 7, throw becomes an expression, so it's fine to use exactly the code described in the question.

For C# 6 and earlier

You can't do that directly in C# 6 and earlier - the second operand of ?? needs to be an expression, not a throw statement.

There are a few alternatives if you're really just trying to find an option which is concise:

You could write:

public static T ThrowException<T>() {     throw new Exception(); // Could pass this in } 

And then:

return command.ExecuteScalar() as int? ?? ThrowException<int?>(); 

I really don't recommend that you do that though... it's pretty horrible and unidiomatic.

How about an extension method:

public static T ThrowIfNull(this T value) {     if (value == null)     {         throw new Exception(); // Use a better exception of course     }     return value; } 

Then:

return (command.ExecuteScalar() as int?).ThrowIfNull(); 

Yet another alternative (again an extension method):

public static T? CastOrThrow<T>(this object x)      where T : struct {     T? ret = x as T?;     if (ret == null)     {         throw new Exception(); // Again, get a better exception     }     return ret; } 

Call with:

return command.ExecuteScalar().CastOrThrow<int>(); 

It's somewhat ugly because you can't specify int? as the type argument...

like image 179
Jon Skeet Avatar answered Oct 11 '22 14:10

Jon Skeet


As has been said, you can't do this with the ?? operator (well, not without some contortions that don't seem to fit with your aim of making this cleaner).

When I see this pattern emerging I immediately think of Enforcements. Originally from the C++ world they transfer to C# pretty well, although are arguably less important most of the time.

The idea is that you take something of the form:

if( condition ) {   throw Exception; } 

and converts it to:

Enforce<Exception>( condition ); 

(you can further simplify by defaulting the exception type).

Taking it further you can write a set of Nunit-style methods for different condition checks, e.g.;

Enforce<Exception>.NotNull( obj ); Enforce<Exception>.Equal( actual, expected ); Enforce<Exception>.NotEqual( actual, expected ); 

etc.

Or, better still by providing an expectation lamba:

Enforce<Exception>( actual, expectation ); 

What's really neat is that, once you've done that, you can return the the actual param and enforce inline:

return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value; 

... and this seems to be the closest to what you're after.

I've knocked up an implementation of this before. There's a couple of little niggles, like how you generically create an exception object that takes arguments - some choices there (I chose reflection at the time, but passing a factory in as an extra parameter may be even better). But in general it's all pretty straightforward and can really clean up a lot of code.

It's on my list of things to do to knock up an open source implementation.

like image 27
philsquared Avatar answered Oct 11 '22 13:10

philsquared