例外 - 最佳实践

时间:2012-11-16 19:19:02

标签: c# exception exception-handling

我一直在考虑异常处理。

根据提供的username参数实现获取User对象的方法的最佳做法是什么。见下文。

    /// <summary>
    /// Gets a user.
    /// </summary>
    /// <param name="username">Username</param>
    /// <returns>User instance</returns>
    public Model.User GetUser(string username)
    {
        return Context.Users.SingleOrDefault(u => u.Username.ToLower() == username.ToLower());
    }

如果没有用户存在username参数,最好返回一个空User对象,或者抛出一个指定用户不存在的自定义异常。

5 个答案:

答案 0 :(得分:2)

我的建议是,如果程序无法在没有用户的情况下继续,那么抛出异常。如果您无法找到用户,或者这将是登录失败,那么我将返回null。如果程序无法在没有获取用户的情况下继续执行,我只会抛出异常,并且无法再次重定向到登录。

记住抛出一个异常更多是一个昂贵的操作,它也返回null(我的意思是没有什么值得注意的,并且这样做(微优化)但是异常应该用于正常的业务逻辑)

答案 1 :(得分:2)

抛出异常。否则,您的呼叫者和呼叫者的呼叫者以及其他所有人都需要检查null,或者需要处理空集合。

如果这是一个通用方法,意味着在调用者知道的上下文中使用,他需要检查null,那么我的做法有点不同。如果没有匹配的用户,我会有一个private方法返回null。我会添加一个使用“try”模式的调用者:

public bool TryGetUser(string username, out Model.User user)

也是一个只返回用户,但如果找不到则抛出异常

public Model.User GetUser(string username)

答案 2 :(得分:1)

首先,我只是建议对比较字符串的方法进行改进,而不区分大小写。

/// <summary>
/// Gets a user.
/// </summary>
/// <param name="username">Username</param>
/// <returns>User instance</returns>
public Model.User GetUser(string username)
{
    return Context.Users.SingleOrDefault(u => 
       string.Compare(u.Username, username, true));
}

String.Compare on MSDN

现在我对此问题的建议

而不是返回null。您可能希望使用null object pattern返回Null对象。

public class User
{

  public static readonly User Null = new Null{Username = "Anonymous"};

  ...

}

然后你的方法变成:

public Model.User GetUser(string username)
{
    return Context.Users.SingleOrDefault(u => 
       string.Compare(u.Username, username, true)) ?? Model.User.Null;
}

这在null不合需要的情况下非常有用。它无需在以后检查null。例如,如果此用户对象具有关联权限,则可以确保“空用户”没有权限。

答案 3 :(得分:0)

我想说调用方法可以决定是否找不到用户的结果需要抛出异常。如果提供了用户名但未找到,则返回null对我有意义,并让调用代码决定如何继续。

考虑到方法的通用性,如果找不到提供的用户名,为什么会抛出异常?如果发生数据库错误等是一回事,但如果SELECT没有产生任何行,我认为这并不例外。

答案 4 :(得分:0)

我不同意之前发布的答案。

例外情况只能在例外情况下使用。未能找到匹配值也不例外。 IMO,返回null更优雅 - 它决定是否向调用者抛出异常,而不是被调用者,这是有道理的;你问用户的方法,如果没有,则不返回任何内容。

此外,您的代码和其他答案每次都会遍历整个集合,这将会非常缓慢。您应该使用字典进行快速查找(当然,除非对Users集合进行频繁更改,否则无法进行缓存)。

示例:

class MyClass
{
    private Dictionary<String,User> _userLookup;

    public MyClass()
    {
        _userLookup = Context.Users.ToDictionary(u => u.UserName.ToLower());
    }

    private User getUserByName(String name)
    {
        var lowerName = name.ToLower();
        return _userLookup.ContainsKey(lowerName) ? _userLookup[lowerName] : null;
    }     
}