此示例中的i
何时可以取消分配?
int i;
try
{
i = 2;
}
catch
{
i = 3;
}
finally
{
string a = i.ToString();
}
答案 0 :(得分:6)
例如,你可以在i = 2次运行之前得到一个ThreadAbortException。无论如何,C#编译器不是特别聪明,所以很容易愚弄像上面这样的人为例子。它不必识别所有情况,如果它不确定它被分配,即使你确定,它也会抱怨。
答案 1 :(得分:2)
使用您发布的示例极不可能发生这种情况。但是,在这种情况下,compliler会“有用”。正如Hadas所说,只需将i初始化为0。
答案 2 :(得分:2)
有许多代码示例可以编写,其中可以证明分配了一个变量,但编译器根本无法证明它是明确分配的。
考虑一下这个更简单的案例:
int i;
if ((bool)(object)true)
i = 0;
Console.WriteLine(i);
这种情况显然不可能永远访问未分配的i
,但它不会编译。
在一般情况下,编译器也无法解决此问题。在某些情况下,它可以证明变量肯定没有明确分配,并且有些情况下它可以证明它肯定 分配,但也有一些情况,它只是不知道任何一种方式。在那些情况下,它选择失败,因为它看到一些误报错误,而不是假阴性。
详细说明您的具体案例;你说如果在try
和catch
块中分配了一个变量,它就是明确分配的。虽然对于您的特定代码可能也是如此,但在一般情况下肯定不是这样。您需要考虑catch
块未处理的异常(即使在您的情况下,未指定任何内容,也不会捕获堆栈溢出或内存不足等异常),您需要考虑catch块本身抛出异常(同样,在你的情况下不会发生,但编译器需要证明编译代码)。
答案 3 :(得分:0)
我认为如果你看一下除了原语之外的其他类型会有所帮助。考虑:
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();
...
}
因此,在这段代码中,任何一个执行分支都没有字典保证。您需要考虑两个(至少)分支:try-finally分支和try-catch分支。由于函数" getIntFromFunctionThatWillThrow"将要抛出(看看我在那里做了什么?)即使我稍后尝试使用它,我也会被取消分配。但是,这不是在运行之后才能识别的东西,就像我不知道如果我没有关于ed成员的内部信息,这将会进入哪个代码段。所以编译器不知道我将成为什么样的价值。它只知道它存在,并且是int类型。
如果这是一个问题,修复是将i设置为初始值,这将抑制错误。
我希望这有点帮助!