2

我一直在考虑异常处理。

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对象还是抛出一个指定用户不存在的自定义异常。

4

5 回答 5

2

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

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

于 2012-11-16T19:21:18.593 回答
2

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

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

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

还有一个只是简单地返回用户,但如果找不到则抛出异常

public Model.User GetUser(string username)
于 2012-11-16T19:23:34.283 回答
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));
}

MSDN 上的字符串比较

现在我对这个问题的建议

而不是返回null。您可能希望使用null 对象模式返回一个 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以后检查的需要。例如,如果此用户对象具有关联的权限,您只需确保“空用户”没有权限即可。

于 2012-11-16T19:29:39.690 回答
0

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

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

于 2012-11-16T19:24:35.990 回答
0

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

例外只应在特殊情况下使用。未能找到匹配值并不例外。IMO,返回null要优雅得多——它将是否向调用者抛出异常的决定留给调用者,而不是被调用者,这是有道理的;你问一个用户的方法,如果没有,它什么也不返回。

此外,您的代码和其他答案每次都会遍历整个集合,这将是不必要的缓慢。您应该使用字典进行快速查找(当然,除非用户集合经常发生更改,导致无法进行缓存)。

例子:

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;
    }     
}
于 2013-01-04T18:41:37.123 回答