Chris Beaulieu
Chris Beaulieu

Reputation: 340

Why doesn't the compiler detect that an exception will be thrown here?

I am trying to wrap my exception throwing logic into another class so that it is easier to throw custom exceptions. Every class would use either a direct reference to this Thrower class, or an interface, whatever is most appropriate.

I have written a simple class that handles it and it works for the most part, but I have encountered a situation in methods with return types where, even though an exception will always be thrown, the compiler fails to detect it and complains that not all paths return a value.

The following code shows an simplified form of the structure of the Thrower class and any class which would use said Thrower.

public class Thrower
{
    public void ThrowException()
    {
        throw new Exception("Im an exception");
    }
}

public class Foo
{
    // Does not work, compiler complains about not all paths returning values.
    public int ExceptionNotDetected(bool shouldThrow)
    {
        if (!shouldThrow)
        {
            return 1;
        }
        var thrower = new Thrower();
        thrower.ThrowException();
    }

    // Works fine.
    public int ExceptionDetected(bool shouldThrow)
    {
        if (!shouldThrow)
        {
            return 1;
        }
        throw new Exception("Im an exception");
    }
}

As far as I can see the method that uses the Thrower must either return a value or throw an exception. From that it seems that the method ExceptionNotDetected and ExceptionDetected are functionally equivalent.

Why then does the compiler complain about ExceptionNotDetected?

Edit:

In regards to the design, this was purely for illustration purposes as all I really wanted to do is understand what was happening. I apologize if I didn't clarify this properly in the post description. That being said I appreciate the advice in regards to structure.

Upvotes: 2

Views: 478

Answers (3)

Phil1970
Phil1970

Reputation: 2623

Simply because the compiler does not analyse the code inside a function to detect that the function always throw an exception.

C# does not seems to have a "never return" attribute. See: Is there a standard "never returns" attribute for C# functions?

But also, there are no reason to write code that way:

  1. You should use different exception type if they are very specific. Thus you will throw it by calling throw new MyExceptionType(my_parameters);.
  2. If the creation is somewhat more complex, then you would add a static method to your class to create the exception object: throw new MyExceptionType::CreateFromThatData(…);
  3. If you throw the exception only from a single class, then you might have a static function in that class to create the appropriate exception object. That way, you can return different Exception type depending on some conditions. All C# exception derives from Exception.
  4. If you really want a exception factory, then probably a static class with some (static) methods to create desired exception would works.
  5. In your code, I don't really see the point to create a thrower object and then call a method on it to throw the exception. You know need 2 lines of code to throw an exception instead of one.
  6. Hiding the throw call inside a function make the code harder to understand and validate. Does thrower.ThrowException really throw an exception and which one.
  7. And as indicated in other answers, you can put first method calls that raise exception so the compiler would not report that some part do not returns a value.

You are over-complicating your design and your code and as such creating more problems than you solve.

Upvotes: 1

faester
faester

Reputation: 15076

Since c# does not have checked exceptions like Java, rhere is no way the compiler can know that the thrower actually throws.

But you can invert the logic

 if (shouldThrow)
    {
    var thrower = new Thrower();
    thrower.ThrowException();
    }
    return 1;

That way the compiler will assume 1 is returned and that the ThrowException medthod is a regular void which like any other void method might throw and exception.

Upvotes: 3

Hoss
Hoss

Reputation: 420

The compiler can only see the return type of the current method, the "ThrowExeption()" method returns nothing (void).

It won't check inside the called method to see if that is going to return an exception or not.

Upvotes: 4

Related Questions