【问题标题】:Is it possible to change the return value in a finally clause in C#?是否可以在 C# 的 finally 子句中更改返回值?
【发布时间】:2013-04-09 01:04:59
【问题描述】:

假设您有一个 C# 方法,在 try 块内有一个 return 语句。是否可以修改finally块中的返回值?

finally 块中使用return 的明显方法是行不通的:

String Foo()
{
    try
    {
        return "A";
    }
    finally
    {
        // Does not compile: "Control cannot leave the body of a finally clause"
        return "B";
    }
}

有趣的是,这个可以在VB中完成:Return里面Finally是被禁止的,但是我们可以滥用这个事实(可能是出于向后兼容的原因)VB仍然允许返回值通过将其分配给方法名称来进行修改:

Function Foo() As String    ' Returns "B", really!
    Try
        Return "A"
    Finally
        Foo = "B"
    End Try
End Function

注意事项:

  1. 请注意,我提出这个问题纯粹是出于对科学的好奇;显然,这样的代码极易出错且令人困惑,不应该编写。

  2. 请注意,我不是询问try { var x = "A"; return x; } finally { x = "B"; }。我知道这不会改变返回值和I understand why this happens。我想知道是否有种方法可以通过 finally 块来更改 try 块中设置的返回值。

【问题讨论】:

  • 停止滥用 VB.NET - 它已经受到了足够的滥用!
  • 仅仅因为你可以在VB中做到这一点并不意味着你应该
  • 停止使用 VB.NET - 它已经够用了!
  • @MattWilko:我从来没有声称你应该——看我问题的最后一句话。
  • 我不会称这是对 VB 的滥用,它更像是 VB 滥用程序员,并通过其奇怪的临时规则和不一致将他们引向错误的轨道。

标签: c# vb.net return


【解决方案1】:

假设您在 try 块中有一个带有 return 语句的 C# 方法。是否可以修改 finally 块中的返回值?

没有。

您可以在 finally 块之外修改返回值

static int M()
{
    try
    {
        try
        { 
            return 123;
        }
        finally
        {
            throw new Exception();
        }
    }
    catch
    {
        return 456;
    }
}

仅仅因为最初有一个“返回 123”并不意味着该方法将返回 123,如果这正是您的问题所要解决的问题。此方法返回 456。

【讨论】:

  • 非常有趣。似乎唯一的豁免规则是在 finally 块内引发异常。
  • @BradM:你是对的。更一般地说:finally 块内只有三种可能的控制流:(1)永不离开,(2)正常离开,或(3)通过抛出异常离开。 returngotobreakcontinueyield returnyield breakawait 等其他控制流要么在 finally 块中不合法,要么仅在它们跳转到某个位置时才被允许 finally 块中。
【解决方案2】:

VB.NET 版本滥用了 VB6 时代的残留构造,在该构造中,您通过将值分配给函数名称来返回值。

真正有趣的是,在使用标准 return 语句与 myFunc = "B" 时产生的 IL 是否存在差异,因为 try...catch...finally 语义似乎表明这是不可能的更改 return 语句返回的值。

【讨论】:

  • MyFunc = "B" 不返回,因此 IL 将不一样
【解决方案3】:

您可以执行以下操作来达到相同的效果:

private string myFunction()
{
    string result = String.Empty;
    try
    {
        //..
        result = "something";
    }
    finally
    {
        result = "something else";
    }
    return result;
}

【讨论】:

  • 再次阅读问题。问题开始于“假设您在 try 块中有一个 return 语句”。你的 try 块中的 return 语句在哪里?
  • 再次阅读我的答案.. “.. 达到相同的效果”.. 这是一种替代方案,而不是解决方案,因为这是不可能的。没有理由投反对票..
【解决方案4】:

与引用的 VB 方法非常相似的是,将修改后的值分配给 return 使用的变量(这样做的好处是保留了单点返回控制):

string returnResult;

try
{
    returnResult = "A";
}
finally
{
    returnResult = "B";
}

return returnResult;

【讨论】:

  • 再次阅读问题。问题开始于“假设您在 try 块中有一个 return 语句”。你的 try 块中的 return 语句在哪里?
  • 告诉用户“不要那样做,而是那样做”并没有错——仅仅给他们问题的答案并不总是正确的做法如果他们试图做的事情是错误的。
  • 问题的最后一段表明原发帖人知道这是不好的风格。
猜你喜欢
  • 1970-01-01
  • 2020-02-12
  • 2014-10-31
  • 2019-06-17
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 2013-05-15
相关资源
最近更新 更多