2012-05-24 107 views
6
string foo; 
try 
{ 
    foo = "test"; // yeah, i know ... 
} 
catch // yeah, i know this one too :) 
{ 
    foo = null; 
} 
finally 
{ 
    Console.WriteLine(foo); // argh ... @#! 
} 
Console.WriteLine(foo); // but nothing to complain about here 

除了它不是BP(捕捉路由) - 但这是我能得到的最好的隔离。
但是我收到了很好的信息,告诉我“危险,危险 - 可能未初始化”。 怎么回事?为什么我的变量仍然是“未初始化”?

编辑:
请不要建议“简单地说一个string foo = string.Empty;在‘声明’”。我想宣布它,但只是按时完成任务!

+0

指定一个null,这是有效的,并会安抚编译器,然后完全摆脱捕获。 –

+0

@AdamHouldsworth我已经提到这是一个孤立的例子,对不对?我必须在我的*真实*场景中使用catch,因为我在其中有一些其他代码:) –

+0

是的,但您尚未提供一个可靠的参数,以便在事先没有使用null初始化它。你在另一评论中表示你不想这样做。 Manojlds的答案可能是原因,最终被认为是超出了试用范围,所以MSDN文档条目依然存在。 –

回答

2

从C#规范(5.3.3.14)一些背景资料:

对于形式的try语句stmt:

试试块终于最后 - 块

(...)

终止块 开始处v的明确赋值状态与在 stmt开头的v的明确赋值状态相同。

编辑尝试捕获,最后(5.3.3.15):

仿佛语句是一个拉升一个try-catch-finally语句(...) 明确赋值分析完成 - 最后陈述包围 try-catch语句

下面的例子演示了尝试 语句(第8.10节)的不同块如何影响明确赋值。

class A 
{ 
    static void F() 
    { 
    int i, j; 
    try { 
     goto LABEL; 
     // neither i nor j definitely assigned 
     i = 1; 
     // i definitely assigned 
    } 
    catch { 
     // neither i nor j definitely assigned 
     i = 3; 
     // i definitely assigned 
    } 
    finally { 
     // neither i nor j definitely assigned 
     j = 5; 
     // j definitely assigned 
    } 
    // i and j definitely assigned 
    LABEL:; 
    // j definitely assigned 
    } 
} 

我只是在想说明什么问题更好的例子:

int i; 
try 
{ 
    i = int.Parse("a"); 
} 
catch 
{ 
    i = int.Parse("b"); 
} 
finally 
{ 
    Console.Write(i); 
} 
+0

但我有尝试块,catch-block,finally-block –

+0

@AndreasNiedermair我为Try-Catch-Finally添加了引号。 –

+0

啊,那些f * ckin'goto's :) –

-2

尝试

string foo = string.Empty; 
+0

我已经问过'为什么'不'我该如何解决这个问题...... –

2

你必须在第一线更改为string foo = null或根据需要初始化。就编译器而言,在try块中初始化foo之前可能会有异常,并且捕获也可能不会发生。

+0

哦......来吧......编译器是如此聪明以及其他问题... –

+1

如果编译器无法保证它选择安全路径 - 错误或警告,那么重要的部分就是对捕获缺乏保证。 –

+0

@AdamHouldsworth对于我的场景来说,确保捕捉安全路径的任何模式?顺便说一句,你能给我一些关于“缺乏保证”的说明吗?那真是太棒了! –

-2

试试这个:

string foo = null; 
try 
{ 
    foo = "test"; // yeah, i know ... 
} 
catch // yeah, i know this one too :) 
{ 
} 
finally 
{ 
    Console.WriteLine(foo); // argh ... @#! 
} 
Console.WriteLine(foo); // but nothing to complain about here 
+0

我问过'为什么'而不是'我该如何解决这个问题'...... –

0

在类级别声明您string foo它会解决这个问题

编辑:

string foo = "default"; 
try 
{ 
    foo = "test"; 
} 
catch (Exception) 
{ 
    foo = null; 
} 
finally 
{ 
    Console.WriteLine(foo); 
} 
+0

- ,这是不是线程安全的,没有额外的锁定 –

+0

@AndreasNiedermair然后初始化字符串foo'之前尝试赶上' – Darshana

+0

然后调整你的答案。 –

2

我认为问题可能是有trycatch抛出异常的情况。在这种情况下,finally应仍然可以达到,但未初始化foo。因为在那种情况下,其余的代码将不会被触及(在catch区块中引发的例外将使我们脱离finally之后的方法),但这对于finally之后的代码没有任何问题。该代码只能在trycatch块运行时才能达到。

因为总是有每一个分配给foo抛出异常,并且因为在这种情况下,finally块总是想运行的情况下,总有foo未初始化的可能性。

据我所知,唯一的解决办法是为foo提供初始化值。

+0

我同意。但:(我相信)编译器会得到那个:) ......真正的问题是“最后”超出了范围“ –