Convincing C # compiler that execution will stop after member returns

I don’t think that at present it is possible, or if it’s even a good idea, but that’s what I was thinking now. I use MSTest to unit test my C # project. In one of my tests, I do the following:

MyClass instance; try { instance = getValue(); } catch (MyException ex) { Assert.Fail("Caught MyException"); } instance.doStuff(); // Use of unassigned local variable 'instance' 

To compile this code, I need to assign the value of instance either in the declaration or in the catch . I could alternatively return after Assert.Fail , but this is still a workaround instead of the compiler, just knowing that execution cannot continue after this point. Assert.Fail never, as far as I know, allows execution, so instance will never be used without a value. Why then should I assign meaning to it? If I changed Assert.Fail to something like throw ex , the code compiles fine, I guess, because it knows that the exception will reject execution in order to go to the point where instance will be used uninitialized.

On the contrary, what if I do not want the test to fail, but rather designated as inconclusive? I could do Assert.Inconclusive instead of Fail , and it would be nice if the compiler knew that execution would not continue after that.

So, is this a case of runtime and compile-time knowledge of where execution will continue? Would it be reasonable if C # had some way of saying that a member, in this case Assert.Fail , would never allow execution after it returns? Perhaps this could be in the form of a method attribute. Would this be useful or unnecessary complexity for the compiler?

Outdoor unit tests

Since people [really] point out that this is a dumb way to write unit test, consider my question outside the scope of unit testing:

 MyClass instance; if (badThings) { someMethodThatWillNeverReturn(); } else { instance = new MyClass(); } instance.doStuff(); 

Here, I could potentially replace the call to someMethodThatWillNeverReturn an exception, and perhaps if I had things, I could do this in the constructor for the exception.

Resharper Values

If I add return after Assert.Fail or Assert.Inconclusive , the colors of Resharper return grayed out and have a tooltip that says "The code is heuristically unavailable."

+4
source share
5 answers

Yes, it would be wise to have something indicating that the member will never end normally - i.e. claiming that the dot after the member was unavailable. (This can be either due to an exception, or due to cyclization forever.)

You want something to happen (both in the CLR and in the compiler) to make a backup plan if you are mistaken: what happens if someone changes Assert.Fail to return normally? You might want the code verification part to be verified, it will never return normally.

I believe there is a blog post about this idea from someone at Microsoft ... I will see if I can find it.

In terms of the syntax for representing it, while an attribute is an obvious idea, I really like the idea of ​​a return type of "never". Obviously, this could potentially run into existing types of never, but hey ...

In terms of its usefulness: an obvious workaround is to throw an exception immediately after approval, but it certainly causes annoyance. (This is usually better than returning, because it means that if the method you write this has a return value type, you do not need to specify a meaningless return value - and you also do not need to ensure that all out parameters are assigned values. ) So this is not required - but I think that would be good. Whether it's the most important thing a C # team can do on a tight budget, it's another matter - just to forestall Eric;)

+3
source

throw ex after Assert.Fail ? Or, better, just remove try/catch and Assert.Fail entirely in this case, and let the uncaught exception throw a unit test error for you.

+1
source

One thing I'm curious about: how would the runtime consider this code if you manually compile and execute it? I believe that he checks for errors in the IL code, maybe he catches this "error" ... maybe not :)

+1
source

return after Assert.Fail()

0
source

Seeing that you are claiming that you made a mistake on the exception thrown, why don't you move the whole test to an attempt or get rid of try and let the thrown exception automatically Assert fail.

 try { MyClass instance; instance = MyClass.getValue(); instance.doStuff(); } catch (Exception ex) { Assert.Fail("Caught MyException"); } 

... or...

 MyClass instance; instance = MyClass.getValue(); instance.doStuff(); 
0
source

All Articles