正确使用ArgumentException?

时间:2015-06-22 13:16:27

标签: c# exception

从我所看到的情况来看,ArgumentExceptions通常是这样使用的:

public void UpdateUser(User user)
{
    if (user == null) throw new ArgumentException("user");
    // etc...
}

但如果我有这样的话怎么办:

public void UpdateUser(int idOfUser)
{
    var user = GetUserById(idOfUser);
    if (user == null) throw new ArgumentException("idOfUser");
    // etc...
}

那还是ArgumentException吗?

2 个答案:

答案 0 :(得分:5)

第一个

if (user == null) throw new ArgumentException("user");

应该是

if (user == null) throw new ArgumentNullException("user");

如果可能,你不应该直接抛出ArgumentException

  

ArgumentException的主要派生类是ArgumentNullExceptionArgumentOutOfRangeException。应该使用这些派生类而不是ArgumentException,除非在两个派生类都不可接受的情况下。

对于第二个例子,这里Should I throw a KeyNotFoundException for a database lookup?他们建议(在评论中)

if (user == null) throw new ObjectNotFoundException();

它在System.DataSystem.Data.ObjectNotFoundException中定义。

答案 1 :(得分:0)

顾名思义,ArgumentException是一个关于参数的例外。这意味着论证本质上是错误的。

一般形式是:

public void SomeMethod(SomeType arg)
{
  if(!TestArgValid(arg))
    throw new ArgumentException("arg"); //Or more specific is possible
                                        //e.g. ArgumentNullException
    /* Actually do stuff */
}

如果 GetUserById可能失败的唯一可能的方式是idOfUser的值本身存在错误,那么以下将会两者在实践中都是一样的:

public void UpdateUser(int idOfUser)
{
  if(!TestValid(idOfUser))
    throw new ArgumentException("idOfUser");
  var user = GetUserById(idOfUser);
  // Do stuff with user
}

public void UpdateUser(int idOfUser)
{
  var user = GetUserById(idOfUser);
  if(user == null)
    throw new ArgumentException("idOfUser");
  // Do stuff with user
}

并且如果结果出于某种原因更快或更少浪费某些资源来测试user之后的事件而不是事件之前的idOfUser如果没有调用GetUserById的副作用,如果差异实际重要,那么可能第二个版本将是合理的优化第一个。

但只有在上面的所有 if 成立时才会成立,这就是检测无效参数的一种奇怪方式,这种参数具有一些特定优势,我们可以通过隐藏方法来封装方法来自其他一切的奇怪。

可能有一个有效的idOfUser可能没有相应的user,在这种情况下它肯定不是一个参数例外。