为什么需要在try和catch部分中初始化out参数?

时间:2015-09-04 18:46:00

标签: c# .net compiler-errors out

我注意到C#编译器(.NET 4.5.2)不允许我编译以下代码:

public void Test(out string value)
{
    //value = null;

    try
    {
        value = null;
    }
    catch (Exception ex)
    {
        //value = null;
    }
}

失败并出现以下错误:

  

out参数'值'必须在控制离开之前分配   目前的方法

但如果我取消注释catch部分中的作业,则会成功编译。
显然,当我在try语句之前取消对作业的注释时,它也会编译。

所以问题是为什么它不足以在try块中初始化out参数?为什么我被强制在{{进行初始化? 1}}阻止?

4 个答案:

答案 0 :(得分:6)

原因是out关键字保证在退出方法之前将参数分配给参数。因此,如果在执行value = null;行之前引发异常并且在catch块中没有对该参数进行赋值,那么该保证就会被破坏。

如果你有一个if else语句,其中两个逻辑块中的一个没有执行赋值,那么它们是否相同。

正如the MSDN所述,outref的相似之处在于,对此参数所做的分配将使自己脱离方法,但ref不会使同样的保证。因此,如果所需结果为try catch catch块中没有分配,那么您可能需要ref关键字。

此外,如果此赋值是try块中的最后一行,您可以在逻辑上将其移动到finally块,这可以保证在发生异常时它将执行try因此满足out的要求。

答案 1 :(得分:3)

必须在你的函数体中设置out参数。因为try块中的代码可能会执行也可能不会执行(因为可能会抛出错误并且控制权可能会转移到错误处理程序中),所以必须在离开函数之前将变量设置为某个位置。在catch阻止是有效的地方,在try { ... } catch{ ... }之前/之后,或finally { ... }阻止

答案 2 :(得分:3)

根据C#Sepcification,其中说

  

必须在function member returns(通过return statementthrough execution reaching the end of the function member body)的每个位置明确指定函数成员的所有输出参数。这可以确保函数成员不会在输出参数中返回未定义的值,从而使编译器能够考虑一个函数成员调用,该调用将变量作为输出参数,等同于对变量的赋值。

如果try..catch,该函数可以从Try或from catch返回。因此,有两个执行路径,因此,如果output parameters在两个执行路径中都分配了值,则规范编译器会进行编译时间检查。

问题的解决方案是为out parameter分配默认值。稍后您可以使用适当的值在Try中初始化它,编译器不会打扰您。

答案 3 :(得分:1)

编译器没有足够的智能来理解try-block中的代码可能包含多个部分,不会失败的部分以及可能失败的部分。

您在try-block中初始化out参数的事实对于编译器来说已经足够了,try-block中的任何内容都可能根本不会发生,因此out参数< 可能在方法返回之前没有给出值,因此你得到了错误。

当您将初始化添加到catch块时,您基本上是说(就编译器可以理解的内容而言)我理解try-block中的代码可能没有完全执行或者根本没有执行,所以请确保这是在你继续之前完成的。