Correct Usage of ArgumentException? - c#

From what I've seen, ArgumentExceptions are usually used like such:
public void UpdateUser(User user)
{
if (user == null) throw new ArgumentException("user");
// etc...
}
but what if I have something like this:
public void UpdateUser(int idOfUser)
{
var user = GetUserById(idOfUser);
if (user == null) throw new ArgumentException("idOfUser");
// etc...
}
Is that still an ArgumentException?

The first
if (user == null) throw new ArgumentException("user");
should be
if (user == null) throw new ArgumentNullException("user");
If possible you shouldn't throw ArgumentException directly
The primary derived classes of ArgumentException are ArgumentNullException and ArgumentOutOfRangeException. These derived classes should be used instead of ArgumentException, except in situations where neither of the derived classes is acceptable.
For the second example, here Should I throw a KeyNotFoundException for a database lookup? they suggest (in comments)
if (user == null) throw new ObjectNotFoundException();
It is defined in System.Data: System.Data.ObjectNotFoundException.

As the name suggests, an ArgumentException is an exception about an argument. It means the argument was somehow inherently wrong.
The general form is:
public void SomeMethod(SomeType arg)
{
if(!TestArgValid(arg))
throw new ArgumentException("arg"); //Or more specific is possible
//e.g. ArgumentNullException
/* Actually do stuff */
}
If the only possible way that GetUserById could fail was that there was something inherently incorrect with the value of idOfUser then the following would both be the same in practice:
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
}
And if it turned out to be for some reason faster or less wasteful of some resource to test user after the fact than idOfUser before the fact and if there were no side-effects of calling GetUserById, and if the difference actually mattered then maybe the second version would be a reasonable optimisation of the first.
But that only holds if all of the ifs above hold, and it's then a weird way of detecting an invalid argument that has some specific advantage where we benefit from the encapsulation of methods by hiding that weirdness from everything else.
Chances are there could be a valid idOfUser for which there was no corresponding user, in which case it certainly wasn't an argument exception.

Related

Should methods handle nulls? best practice in this case?

I have the following situation in code, whats the best way to manage it, the comments contains the situations, and please recommend the best practice.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
// FIRST WAY : REMOVE THIS NULL CHECK AT ALL AND LEAVE GetAccountDetails to control
// the Null situation?
if (accountDetails == null)
{
// Second Way: This way? Throw exception here?
throw new ArgumentNullException(nameof(accountDetails));
//Third way? break the function?
break;
}
// GetAccount Details already has null control
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
First of all, the costruction
catch (Exception e) {
throw;
}
is redundant one and can be eliminated. Now about nulls. There're two
cases:
null is an erroneous value and so it should be signalled
null is an expected, ordinary value and thus it should be proceeded
And so you have (null is an error)
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
// What's wrong: it's id which doesn't correspond to any detail
// (we expect id being s.t. AccountClient.GetAccount(id...) returns not null detail)
if (accountDetails == null)
throw new ArgumentException($"Incorrect id {id} which doesn't have any detail.",
nameof(id));
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
Or (null is an expected outcome)
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
if (accountDetails == null)
return null; // or any reasonable value, or just return, or create new Subscription
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
If you can do anything about null input then handle it.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
if (accountDetails == null)
{
// do something about it. Maybe write some logs, substitute with a default value
// or throw appropriate exception ...
}
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
if you can't then let GetAccountDetails decide what should happen.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
Also there is no need to catch an exception, doing nothing and then throw it so you can remove the whole try catch block.
It depends on where this ID is coming from. If the user typed the ID, then I wouldn't generate an Exception, since it is not a error in your program. Just treat the user input and show a proper message. Exceptions are costly, so I usually use them only when i have a real programa failure. Besides that, if you write a custom Exception Handler, it wouldn`t make sense to log a error caused by wrong user input. So i would make it like this:
if (AccountClient.AccountExists(id))
{
AccountDetails details = AccountClient.GetAccount(id);
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
Anyway, its good to treat the input on the same way, even if you had treated like above, in case there is any other non treated call to it:
public AccountDetails GetAccount(int id)
{
if (Exists(id))
GetTheAccount(id);
else
throw new Exception(String.Format("Account {0} doesn't exists", id));
}
In this case I would use an Exception because it could really represent an error, if the caller function is passing a wrong value, for instance.

How to check exception of a member variable of an object?

Are there any ways to check the exception of a member variable of an object or not?
For example, I have a Recipient object, called rcp. AddressEntry is a member of this object. I want to check the exception of the member before using AddressEntry.
I want to code a method to check the member variable, but I have no ideas. Do not use try-catch
private voice GetEmail(Outlook.NameSpace otl, string email){
//...
Recipient rcp = otl.CreateRecipient(email);
if (rcp != null && CheckException(rcp))
{
//do my code
}
//...
}
private bool CheckException(Recipient rcp)
{
//if AddressEntry of rcp object does not threw exception, return true
return false;
}
Could you give me advises or suggestions about this!
Doing control flow based on exceptions is known an anti-pattern.
You need to develop your code in a way that it doesn't know if it's going to throw an exception, and if it does it, you need to catch these exceptions and recover your application or show an error to the user through the user interface to notify that the whole application is about to crash.
Exceptions are exceptional cases and you need to focus on regular cases.
I would argue that your code should look something like this:
try
{
Recipient rcp = otl.CreateRecipient(email);
if (rcp != null)
{
//do my code
}
//...
}
catch(COMException e)
{
// Show a message box, alert, whatever relevant to your users
}

Getting NullReferenceException in impossible situation (when checking for null)

I have a very simple check right at the beginning of one of my methods as follows:
public void MyMethod(MyClass thing)
{
if(thing == null)
throw new ArgumentNullException("thing");
//Do other stufff....
}
But I'm getting stacktraces (from Elmah in a production environment) which appears to indicate that the "if(thing == null)" line is throwing a NullReferenceException. The first 2 lines of the stack trace are something like:
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at MyLibrary.BL.AnotherClass.MyMethod(MyClass thing) in C:\Development\MyProject\trunk\MyLibrary.BL\AnotherClass.cs:line 100
MyClass is a fairly simple class with no operator overloads or anything like that, so I'm a bit stumped as to what is throwing the NullReferenceException!
Can anybody suggest scenarios that might cause this?
EDIT: I suspect "thing" might be null, but I really would expect an ArgumentNullException not a NullReferenceException - this is basically what this question is about. Is there maybe something that the framework or Elmah that is changing or mis-reporting the exception - or is the only explanation that the binaries are somehow out of date?
It is impossible for if (thing == null) to throw a NullReferenceException.
This means that something else is going on. It's time to start using your imagination in conjunction with a firm resolve to ignore the possibility that the if caused a problem.
The if statement can throw a NullReferenceException if MyClass defines the == operator incorrectly e.g.
class MyClass
{
int A {get;set;}
public static bool operator ==(MyClass a, MyClass b)
{
return a.A == b.A;
}
public static bool operator !=(MyClass a, MyClass b)
{
return !(a == b);
}
}
Looks like the exception is coming from something up the chain that calls MyMethod. MyMethod() is throwing the Exception and nothing above is handling it, so whatever web framework you're in is throwing the HttpUnhandledException.
I also encountered this impossible situation. It turned out to be due to the use of the as keyword, I have no idea why. I was using the SharpPdf library and had a line of code like this:
var destElement = annotDict.Elements["/Dest"] as PdfName;
if (destElement == null)
{
continue;
}
If I remove the as PdfName portion, it works. So I now have two levels of checking in my code:
var destElement = annotDict.Elements["/Dest"];
if (destElement == null)
{
continue;
}
var destElementName = destElement as PdfName;
if (destElementName == null)
{
continue;
}
thing is null.
That would cause it.
[EDIT]: Here's the code I tested with:
protected void Button3_Click(object sender, EventArgs e)
{
MyMethod(null);
}
public void MyMethod(String thing)
{
if (thing == null) // This caused the exception to be thrown.
throw new Exception("test");
//Do other stufff....
}

uplifitng return value error reporting to Exceptions

In Framework Design guideline book there is a chapter about Exception and they talk about return-value-based error reporting and exception based error reporting and the fact that we in a O.O language like C# we should avoid return-value-based error reporting and use exceptions. With that in mind I was looking at our code that eight years ago was written in Visual Basic and last year with a automatic tool got converted to C#!
So here is a method I am looking at, I was wondering if the advice from that book applies to such a method and if yes, then what would be a better approach for rewriting this method?
public int Update(CaseStep oCaseStepIn)
{
int result = 0;
//Update the master object with the passed in object
result = UCommonIndep.gnUPDATE_FAILED;
if (Validate(oCaseStepIn) == UCommonIndep.gnVALIDATE_FAILED)
{
return result;
}
CaseStep oCaseStep = get_ItemByObjectKey(oCaseStepIn.CopyOfObjectKey);
if (oCaseStep == null)
{
return result;
}
return result;
}
Throw specific exceptions when possible. Then, you don't need a return value in this case.
public void Update(CaseStep oCaseStepIn)
{
//Update the master object with the passed in object
if (Validate(oCaseStepIn) == UCommonIndep.gnVALIDATE_FAILED)
throw new ValidationFailedUpdateException();
CaseStep oCaseStep = get_ItemByObjectKey(oCaseStepIn.CopyOfObjectKey);
if (oCaseStep == null)
throw new KeyObjectNotFoundUpdateException();
if (oCaseStep.Update(oCaseStepIn) != UCommonIndep.gnUPDATE_SUCCESSFUL)
throw new UpdateFailedException();
//*******************************
//FYI - Insert code here to update any Key values that might have changed.
}
UpdateFailedException extends Exception
ValidationFailedUpdateException extends UpdateFailedException
KeyObjectNotFoundUpdateException extends UpdateFailedException
There are (at least) as many opinions on exception handling as there are coders, but a good rule of thumb to start from is that exceptions should be thrown in exceptional circumstances.
So, is an update failure an exceptional occurrence?

Constructors and throwing exceptions

Is this the best way for me to abort instantiation of an object if it's parameters are not passed in with valid data?
protected Command(string commandKey)
{
if(commandKey == null) throw new ArgumentNullException("commandKey", "Command Key cannot be null as it is required internally by Command");
if(commandKey == "") throw new ArgumentException("Command Key cannot be an empty string");
CommandKey = commandKey;
}
Yes. It is common practice to validate the arguments in constructors and throw an exception if they are invalid.
It's perfectly fine. Constructors do not return anything so how else would you know if something went wrong? You could have a bool to set it to some uninitialized state but I would go with exceptions.
Also :
if(String.IsNullOrEmpty(commandKey)) //throw exectpion
In this case you could use the static method string.IsNullOrEmpty(commandKey):
protected Command(string commandKey)
{
if(string.IsNullOrEmpty(commandKey))
throw new ArgumentException("commandKey");
//something
}
This is exactly what Microsoft does if you look through the framework source code, so I suspect it is perfectly valid.
It is perfectly fine if you validate inside a constructor and throw exception if something goes wrong.

Categories