在方法中写“返回”的最佳方法是什么

时间:2012-01-15 21:56:30

标签: c# coding-style resharper

我不喜欢方法有几条返回线。所以我用字符串结果创建了一个返回值 - 在每种情况下我都写了result = something ...

但是当我编写“try-catch”机制时,我必须设置公共字符串结果。因为,如果我在try中返回一个结果,编译器将启动错误,并说并非所有代码都有返回值。如果我将 result = string.Empty 写入方法的末尾,resharper说,它是无法访问的代码。所以,这里有一个例子,这是我的问题;

“在方法中写”返回“的完美方式是什么?”

    public static string PingThatAddress(string hostAddress)
    {
        try
        {
            Ping ping = new Ping();
            PingReply pingreply = ping.Send(hostAddress);

            string result;
            if (pingreply != null && pingreply.Status.ToString() != "TimedOut")
            {
                result = "Address: " + pingreply.Address + "\r"
                     + "Roundtrip Time: " + pingreply.RoundtripTime + "\r"
                     + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r"
                     + "Buffer Size: " + pingreply.Buffer.Length + "\r";
            }
            else
            {
                result = string.Empty;
            }

            return result;
        }
        catch (Exception pingError)
        {
            Debug.Fail(pingError.Message + " " + pingError);
        }
        //compiler error: THERE IS NO RETURN VALUE here?
    }

5 个答案:

答案 0 :(得分:4)

你可以这样做:

public static string PingThatAddress(string hostAddress)
{
    string result = string.Empty;
    try
    {
        Ping ping = new Ping();
        PingReply pingreply = ping.Send(hostAddress);

        if (pingreply != null && pingreply.Status.ToString() != "TimedOut")
        {
            result = "Address: " + pingreply.Address + "\r"
                 + "Roundtrip Time: " + pingreply.RoundtripTime + "\r"
                 + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r"
                 + "Buffer Size: " + pingreply.Buffer.Length + "\r";
        }

    }
    catch (Exception pingError)
    {
        Debug.Fail(pingError.Message + " " + pingError);
    }
    return result;
}

然后确保将result设置为在异常情况下有意义的内容。

如果你想坚持Resharper警告你的事情,那就这样做:

public static string PingThatAddress(string hostAddress)
{
    try
    {
        Ping ping = new Ping();
        PingReply pingreply = ping.Send(hostAddress);

        string result = string.Empty;
        if (pingreply != null && pingreply.Status.ToString() != "TimedOut")
        {
            result = "Address: " + pingreply.Address + "\r"
                 + "Roundtrip Time: " + pingreply.RoundtripTime + "\r"
                 + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r"
                 + "Buffer Size: " + pingreply.Buffer.Length + "\r";
        }
        return result;

    }
    catch (Exception pingError)
    {
        Debug.Fail(pingError.Message + " " + pingError);
    }
    return string.Empty;
}

你不可能双管齐下:你的人工标准没有多个return语句可能是导致你遇到Resharper麻烦的原因。

答案 1 :(得分:2)

有些建议,包括接受答案的第一部分和原始问题,很有可能返回不正确的结果,尤其是在发生例外情况时。

问题,我们已经看到这种情况发生了很多次,当你有一个返回值时,对方法逻辑的微小改动总会导致通过代码的路径,这是原始方法编写者没有预料到的。将导致返回变量在方法中多次设置错误或根本未设置。

有些时候你必须收集一个返回调用者的值,然后在后面的方法中执行一些额外的任务,但总的来说应该是例外而不是规则。

在追踪过多因为希望获得单一回报价值而引入的错误之后,我们的开发标准现在要求return将被使用,除非绝对必要,并且不这样做的原因必须彻底记录在代码中以及后续修饰符的警告。

这种方法的另一个好处是,如果方法的逻辑被修改为新的代码路径在返回逻辑中导致“漏洞”,编译器将自动通知您。使用单个返回值要求开发人员可视地检查每个可能的代码路径,以验证没有遗漏任何内容。

最后,我们要求在异常处理程序中返回适当的默认值,而不是在异常之外返回值。通过这种方式,可以清楚地知道在发生异常时会发生什么。

因此,在我们的环境中,您的代码将是:

public static string PingThatAddress(string hostAddress)
{
    try
    {
        Ping ping = new Ping();
        PingReply pingreply = ping.Send(hostAddress);

        if (pingreply != null && pingreply.Status.ToString() != "TimedOut")
        {
            return "Address: " + pingreply.Address + "\r"
                 + "Roundtrip Time: " + pingreply.RoundtripTime + "\r"
                 + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r"
                 + "Buffer Size: " + pingreply.Buffer.Length + "\r";
        }
        else
        {
            return string.Empty;
        }
    }
    catch (Exception pingError)
    {
        Debug.Fail(pingError.Message + " " + pingError);
        return string.Empty;
    }
}

答案 2 :(得分:2)

所以你声称帮助你到达那个出口点的if语句(或其他程序流程语句)本身并不是一个退出点?该控制语句与return语句之间的唯一区别是return语句实际上更明显,更易读,更易于维护且不易出错。此外,由于return语句可以在任何级别上运行,因此您可能会重复控制语句x次。

想要在结尾处使用return语句的唯一原因是资源处理 - 摆脱您在开始时声明的资源。这在C / C ++中更为常见(即使在C ++中,它也没有那么麻烦)。在Java中,您可以依赖异常机制和finally语句来处理应有的资源(在Java 7中,“尝试使用资源”功能)。

还有其他理由选择return语句。一个是最终标记变量的能力:因为编译器知道return(或者抛出那个问题)是方法的结束,你可以更容易地插入最终变量。最终变量 - 一旦你习惯了它们 - 真的可以很容易地阅读代码并帮助你避免犯错误。

  boolean someErrorCondition = true;
  final int setSomething;
  for (int i = 0; i < 8; i++) {
      if (i == 7) {
          setSomething = 11;
          break;
      }

      if (someErrorCondition) {
          return;
      }
  }

这不适用于您的方法,因为编译器会抱怨最终变量没有被设置(这是整个想法,而不是进入无效状态)。

众多优秀的开发人员和语言设计人员选择了多个返回语句。我会紧急建议任何人不要走向另一个方向。

答案 3 :(得分:0)

如果发生异常,则不返回值。

答案 4 :(得分:0)

多个return语句可以更轻松地遵循您的代码。这样您就可以立即看到不同的方法返回点。相反,返回“结果”字段会强制您查找字段在更改后的使用位置。这使得遵循该方法的自然流程变得更加困难。但无论如何,通常情绪更多的是关于风格偏好。确保不要混用两种方法。