Use of unassigned local variable on finally block

雨燕双飞 提交于 2019-12-23 08:50:13

问题


When could i in this example be unassigned?

int i;
try
{
    i = 2;
}
catch
{
    i = 3;
}
finally
{
    string a = i.ToString();
}

回答1:


You could get a ThreadAbortException before i=2 runs, for example. Anyway, the C# compiler is not exceptionally smart, so it's easy to fool with contrived examples like the above one. It doesn't have to recognize every situation, and if it's not sure it is assigned, even if you are sure, it will complain.

EDIT: I was a bit quick on my first assumption. So to refine it, here's what I think. Code is guaranteed to run in order, or if an exception happens, it will jump to the handlers. So i=2 may not run if an exception happens before that. I still claim that a ThreadAbortException is one of the few reasons why this can happen, even you have no code which could produce exceptions. Generally, if you have any number of different exception handlers, the compiler cannot know in advance which one will run. So it doesn't try to make any assumptions about that. It could know that if 1) there is only 1 catch block and 2) it is typeless, then, and only then, that one catch block is guaranteed to run. Or, if there were multiple catch handlers, and you assigned your variable in every one of them, it could also work, but I guess the compiler doesn't care about that either. However simple it may seem, it is a special case, and the C# compiler team has a tendency to ignore those special cases.




回答2:


It's highly unlikely it will happen with the example you have posted. However, the compliler is going to be 'helpful' in this situation. As Hadas said, just initialize i to 0.




回答3:


There are lots of code samples that one can write in which it is provably the case that a variable is assigned but that the compiler simply cannot prove that it is definitely assigned.

Just consider this much simpler case:

int i;
if ((bool)(object)true)
    i = 0;

Console.WriteLine(i);

It is provably impossible for that case to ever access an unassigned i as well, yet it won't compile.

It is also provably impossible for the compiler to solve this problem in the general case. There are cases where it can prove a variable is certainly not definitely assigned, and there are cases where it can prove it definitely is assigned, but there are also cases where it just doesn't know either way. In those cases it chooses to fail, because it sees a few false positive errors as less harmful than false negatives.

To speak more about your specific case; you're saying that if a variable is assigned in both the try and catch blocks it is definitely assigned. While that may be true of your specific code, it's certainly not true in the general case. You need to consider exceptions that aren't handled by the catch block (even in your case, where none is specified, exceptions such as a stack overflow or out of memory won't be caught), you need to consider the catch block itself throwing an exception (again, it won't happen in your case, but the compiler would need to prove that to compile the code).




回答4:


I think it would help if you to look at another type besides a primitive. Consider:

int i;
MyClass ed = new MyClass();
try
{
   int newI = ed.getIntFromFunctionThatWillThrow();
   i = newI;
}
catch (Exception e)
{
   i = 3;
   // do some abortion code.
}
finally
{
   string a = i.ToString();
   ...
}

So in this block of code, there is no lexicographical guarantee for any one branch of execution. You have two (at least) branches to consider: The try-finally branch, and the try-catch branch. Since the function "getIntFromFunctionThatWillThrow" is going to throw (See what I did there?) i will be left unassigned, even though I try to use it later. However, that isn't something that is recognized until after runtime, like I have no idea what section of code this will get into if I have no inside information about the member on ed. So the compiler has no idea what value i will be. It only knows that it exists, and is of type int.

If it was an issue, a fix is to set i an initial value, this will suppress the error.

I hope this helps somewhat!



来源:https://stackoverflow.com/questions/20521993/use-of-unassigned-local-variable-on-finally-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!