我一直在考虑异常处理。
根据提供的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
对象,或者抛出一个指定用户不存在的自定义异常。
答案 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));
}
现在我对此问题的建议
而不是返回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;
}
}