C#: Any way to suppress compiler errors similar to suppressing warning messages?
Asked Answered
D

3

7

I have the following code that generates a compiler error:

    Boolean IConvertible.ToBoolean(IFormatProvider provider)
    {
        ThrowHelper.ThrowInvalidCast(typeof(MyType), typeof(Boolean));
    }

The compiler is complaining that not all code paths return a value. The problem here is that ThrowHelper will ALWAYS throw an error. It is a static class calling a static method.

I understand that I can satisfy the compiler with a silly "return true" after the ThrowHelper call, but that seems like unnecessary code. I know I can suppress warning messages, but when I tried to use the SuppressMessageAttribute it doesn't stop the compiler from complaining. Any way to suppress this error only for this method?

Diligent answered 14/2, 2011 at 23:2 Comment(0)
K
7

There is no way to suppress an error other than to fix it.

An error, by its nature, is indicating that the compiler believes it cannot generate valid code. The only way to suppress errors is to fix them. Just add the return statement it wants and then raise an issue on Microsoft Connect indicating that you believe the compiler is getting this one wrong.

I suspect, however, that this is expected behaviour as the compiler is not aware that the method you are calling will always throw and to determine that in a predictable manner for any possible call tree would be difficult, if not impossible (imagine if you called a chain of 20 methods before concluding with a throw).

Kayser answered 14/2, 2011 at 23:5 Comment(6)
Creating an item on Connect would be wasted time. There is no way to determine for the compiler in C# that a certain method always throws.Mattie
@0xA3: I agree. I added some comments regarding that myself.Kayser
@JeffYates: I came across my own question and answer again and had another thought about this answer... shouldn't the compiler inline the call and realize that it simply throws an exception? The ThrowHelper.ThrowInvalidCast(typeof(MyType), typeof(Boolean)) method is inside of a static helper class and is a static method itself...Diligent
As far as I am aware, the inlining is done at a different phase of the compilation to detecting unreachable code. So the compiler still will not detect this (as is shown by the fact that it doesn't detect it).Kayser
Not always. Some C# errors are overly pedantic. Use of unassigned local variable 'someFloatLocal' is one I wish I could get around at times. I can see that my code is only assigning a value to a float variable when an enum ivar is a special case, and only I'm using the float value for the same specific enum special case. But the compiler can't apparently, forcing me to either completely restructure my currently-human-logically-organized function, or to cheat the compiler by arbitrarily assigning a likely-invalid value to the float up front (which is my choice— humans rule, machines drool)Mellophone
error CS0165: Use of unassigned local variable also seems to be lambda-blind. I'm doing the assignment unconditionally in an lambda passed to a method which calls the lambda 100% of the time. But alas, still an impassible compiler error.Mellophone
A
10

You could have the method in ThrowHelper only create the exception, not actually throw it.

Boolean IConvertible.ToBoolean(IFormatProvider provider)
{
    throw ThrowHelper.CreateInvalidCast(typeof(MyType), typeof(Boolean));
}

This would probably result in a better stack trace as well: it would point at ToBoolean, not at ThrowInvalidCast.

Advocaat answered 14/2, 2011 at 23:24 Comment(0)
K
7

There is no way to suppress an error other than to fix it.

An error, by its nature, is indicating that the compiler believes it cannot generate valid code. The only way to suppress errors is to fix them. Just add the return statement it wants and then raise an issue on Microsoft Connect indicating that you believe the compiler is getting this one wrong.

I suspect, however, that this is expected behaviour as the compiler is not aware that the method you are calling will always throw and to determine that in a predictable manner for any possible call tree would be difficult, if not impossible (imagine if you called a chain of 20 methods before concluding with a throw).

Kayser answered 14/2, 2011 at 23:5 Comment(6)
Creating an item on Connect would be wasted time. There is no way to determine for the compiler in C# that a certain method always throws.Mattie
@0xA3: I agree. I added some comments regarding that myself.Kayser
@JeffYates: I came across my own question and answer again and had another thought about this answer... shouldn't the compiler inline the call and realize that it simply throws an exception? The ThrowHelper.ThrowInvalidCast(typeof(MyType), typeof(Boolean)) method is inside of a static helper class and is a static method itself...Diligent
As far as I am aware, the inlining is done at a different phase of the compilation to detecting unreachable code. So the compiler still will not detect this (as is shown by the fact that it doesn't detect it).Kayser
Not always. Some C# errors are overly pedantic. Use of unassigned local variable 'someFloatLocal' is one I wish I could get around at times. I can see that my code is only assigning a value to a float variable when an enum ivar is a special case, and only I'm using the float value for the same specific enum special case. But the compiler can't apparently, forcing me to either completely restructure my currently-human-logically-organized function, or to cheat the compiler by arbitrarily assigning a likely-invalid value to the float up front (which is my choice— humans rule, machines drool)Mellophone
error CS0165: Use of unassigned local variable also seems to be lambda-blind. I'm doing the assignment unconditionally in an lambda passed to a method which calls the lambda 100% of the time. But alas, still an impassible compiler error.Mellophone
M
3

A simple brain exercise why the requested feature could lead to problems. Imagine that ThrowHelper.ThrowInvalidCast is defined in some 3rd-party library. You might know that the method always throws and tell the compiler about it or a very advanced static analyzer might be able to determine that the method always throws at the moment the code is compiled.

Now some other developer deploys an updated version of that library. Now the method doesn't always throw. All of a sudden, there is a case that your method has no return path. Just to handle that case the compiler (or the runtime) would have to include a backup plan what to do in such a situation. Quite a lot of overhead for something that can easily be fixed by writing correct code.

UPDATE: Theoretically, C# could be extended to allow for methods with no return path. Eric Lippert mentioned that in a comment to Jon Skeet's answer here:

A "never" method would simply be a void method that is not allowed to have a reachable end point or any return statements. That solves the problem at compile time. At runtime, it's the verifier's responsibility to ensure that methods actually implement their return type semantics correctly; the verifier could similarly determine that there are no return instructions and that the end point is not reachable.

Mattie answered 14/2, 2011 at 23:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.