在 C# 中,为什么在 finally 块的开头没有明确分配变量?

In C#, why is a variable not definitely assigned at the beginning of a finally block?

我不明白为什么下面的代码会产生错误。通常我可以从语言规范中弄清楚,但在这种情况下我不理解语言规范。

这不会导致我的代码出现问题,顺便说一句,我只是想了解该语言。

示例:

bool success;
try
{
    success = true;
}
catch
{
    success = false;
}
finally
{
    Console.WriteLine(success); // ERROR: Local variable 'success' might not be initialized before accessing
}

此行为似乎适用于所有版本的 C#,但下面的引用来自 C# Language Specification 5.0

第 5.3.3.14 节 Try-finally 语句

The definite assignment state of v at the beginning of finally-block is the same as the definite assignment state of v at the beginning of stmt.

这里的"beginning of stmt"指的是整个try-finally语句的开始,也就是在try.

之前

第 5.3.3.15 节 Try-catch-finally 语句

The following example demonstrates how the different blocks of a try statement (§8.10) affect definite assignment.

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
}

谁能解释为什么 success(在我的示例中)或 i(在语言规范示例中)没有在 finally 块的开头明确分配?

  1. 正如 Vikas 所说,异常也可能发生在 catch 块内,将控制权传递给 finally 而无需 运行 整个 catch 块。无法保证任何一项作业都已实际完成。

  2. 为什么要设计语言来让编写错误代码变得更容易?好的代码将只捕获特定的异常,或者捕获并记录所有异常,然后重新抛出它无法识别的异常。只有捕获并忽略所有异常的错误代码甚至可以 运行 进入这种情况。

此外,修复非常简单。

原因很简单 - 无法保证 trycatch 块中的代码会在 finally 块之前执行。

ThreadAbort 异常可能发生在 try 块内,但在赋值执行之前。

运行时代码在抛出异常之后但在 catch 块中的代码执行之前执行(搜索异常处理在 .Net 或 "Structured Exception Handling" 中的工作方式)。

因此,在执行 finally 块之前,try 和 catch 块中的代码可能永远不会执行。