【问题标题】:Throw an exception or just return a string?抛出异常还是只返回一个字符串?
【发布时间】:2018-05-12 21:43:53
【问题描述】:

假设我有这个检查用户详细信息的功能

//check valid user's details.
private bool checkUserDatails(String nickname, String groupId)
{
    //check nickname
    if ((nickname == null || nickname.Trim().Equals("")))
    {
        return false;
    }

    //check groupId
    if (groupId == null)
        return false;

    //convert to int
    int id;
    try
    {
        id = int.Parse(groupId);
    }
    catch (Exception) { return false; }

    //check id
    if (id < 0 | id > 100)
        return false;

    return true;
}

它工作得很好,但调用者函数不知道为什么函数返回 false。我最初的想法是创建自己的异常,例如IncorrectUsernameException 等并抛出它们。我也可以制作返回值字符串并返回“不正确的用户名”。

正确的 C# 方法是什么?

【问题讨论】:

标签: c# exception


【解决方案1】:

遵循 Microsoft 约定(至少在某些地方),这应该如下所示:

private void EnsureValidDetails(string nickname, string groupId)
{
    if (string.IsNullOrWhiteSpace(nickname))
    {
        throw new ArgumentNullException(nameof(nickname));
    }
    else if (string.IsNullOrEmpty(groupId))
    {
        throw new ArgumentNullException(nameof(groupId));
    }

    int parsedGroupId;

    if (!int.TryParse(groupId, out parsedGroupId))
    {
        // or some better wording
        throw new ArgumentException("GroupId is not a valid number."); 
    }

    if (parsedGroupId < 0 || parsedGroupId > 100)
    {
        throw new ArgumentOutOfRangeException("GroupId must be between 0 and 100.");
    }
}

但请注意,这种方法做得比它应该做的要多。 groupId 应该是 int 参数,并且该方法应该只检查值是否在有效范围内:

private void EnsureValidDetails(string nickname, int groupId)
{
    if (string.IsNullOrWhiteSpace(nickname))
    {
        throw new ArgumentNullException(nameof(nickname));
    }
    else if (groupId < 0 || groupId > 100)
    {
        throw new ArgumentOutOfRangeException("GroupId must be between 0 and 100.");
    }
}

然而,这可能不是真正验证这类东西的最佳方式。它当然可以作为一种通用的、独立于框架的方式,但一些 .NET 框架(WPF、WCF、WinForms、ASP.NET)提供了内置方式来执行此操作。

【讨论】:

  • 这种约定称为防御性编码。一种方法应该对你给他们的东西进行防御。因此,当您提供的参数不正确时,它应该通过抛出错误来引发错误。
  • @CodeNotFound 呵呵,所以叫防御性编码……谢谢。
  • 在您的答案中添加一个旁注可能会有所帮助,因为只需在参数声明中将 groupId 的类型更改为 int 而无需解析为 int。
  • @CodeNotFound 我不完全确定是否推荐,这就是我在最后添加评论的原因。
【解决方案2】:

您不应该抛出异常,因为返回值false 可能会经常发生。这将导致相当大的性能下降。相反,您可以使用 enum,例如使用 correctinvalid_nicknameinvalid_id 等值。

enum CheckUserDetailsResult { correct, invalid_nickname, invalid_id }

或者,您可以像这样通过 out 引用提供消息:

private bool checkUserDetails (String nickname, String groupId, out String message)
{
    if (String.IsNullOrEmpty (nickname))
    {
        message = "Invalid nickname!";
        return false;
    }
    //and so on
}

【讨论】:

  • "返回值 false 的情况可能会经常发生。"请解释您从哪里获得该信息,因为 OP 从未提及任何与此相关的内容。出参考?您应该查看一些 c# 指南。 out 关键字必须在需要时使用,而不是用于返回消息
  • @CamiloTerevinto 它会检查用户详细信息,这可能是用户输入的。通常,您不能假设用户总是做出正确的输入,因此用户详细信息无效的情况可能会经常发生。
猜你喜欢
  • 2011-11-09
  • 2015-01-26
  • 2011-04-27
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多