0
votes

I have implemented some static throw helper methods in a net-standard 2.1 (C# 8.0) project.

[DoesNotReturn]
public static void InvalidOperation(String message, String caller, String path, Int32 line)
{
  throw new InvalidOperationException($"{message}\n{caller}|{path}|{line}");
}

I want to use them in a NET 5.0 project like:

public static BitmapSource GetBitmapSource(String uri)
{
    if (Uri.TryCreate(uri, UriKind.RelativeOrAbsolute, out Uri? _uri))
    {
        return new BitmapImage(_uri);
    }

    Throw.InvalidOperation( $"Invalid uri {uri}.");
}

But the the compiler still returns the error CS0161: "Not all code paths return a value"

1
puplic? Ok, you should not use throwing exceptions with methods like Throw.InvalidOperation( $"Invalid uri {uri}."); You may do exception fablic and use like: throw MyExceptionGenerator.InvalidOperation($"Invalid uri {uri}.");, but best practice is generate Exceptions by new operator - you should generate the new exception class and use like: throw new MyInvalidOperaionException($"Invalid uri {uri}.") - Leszek Mazur
I like to use the CallerMemberName, CallerFilePath, and CallerLineAttributes to locate where the exception was thrown. That's why I am using those helper methods. I have seen those helper methods several times. Like here: endjin.com/blog/2020/08/… - MaxMa
The attributes can help the compiler in terms of additional analysis, but as far as I'm aware they still don't allow you to violate the language rules of reachability... the end of your method is still reachable as far as the compiler is concerned. - Jon Skeet
That was not what I wanted to hear, Mr. Skeet. :-( But nevertheless, thanks for clarification. - MaxMa
Thats similar to ExceptionDispatchInfo.Throw. We knows the lines after it are unreachable but the language requires a return. You can put a dummy return or throw null but it's not the nicest thing... Or just switch to the suggestion in the comment above, throw ThrowHelper.Whatever() or switch the order you perform your checks - pinkfloydx33

1 Answers

0
votes

Write the exceptional path first:

public static BitmapSource GetBitmapSource(String uri)
{
    if (!Uri.TryCreate(uri, UriKind.RelativeOrAbsolute, out Uri? _uri))
    {
        Throw.InvalidOperation( $"Invalid uri {uri}.");
    }

    return new BitmapImage(_uri);
}

Now, as far as the compiler is concerned, the method returns.


Another thing to consider is to have the helper method return the exception, instead of throwing it. The method that calls it can throw it. That way the compiler would know that it throws. Which also means you don't get the helper method in the stack trace of the exception.


By the way, for reference of people finding this, I believe the helper method in the question is intended to use these: Reserved attributes: Determine caller information.