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

abatishchev picture abatishchev · Nov 19, 2009 · Viewed 10.9k times · Source

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?

Answer

Jon Skeet picture Jon Skeet · Nov 19, 2009

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...