In C#, should one check references passed to methods against null?
Well, a few months ago I asked a similar question about C and C++, but I've been paying more attention to C# lately due to the 开发者_如何学运维whole "Windows Phone" thing.
So, in C#, should one bother to check against NULL at method boundaries? I think this is different than in C and C++, because in C# one generally can determine whether a given reference is valid -- the compiler will prevent one from passing uninitialized references anywhere, and therefore the only remaining possible mistake is for it to be null. Furthermore, there's a specific exception defined inside the .NET Framework for these things, the ArgumentNullException, which seems to codify what programmers think they should be getting when an invalid null was passed.
My personal opinion is once again that a caller doing this is broken, and that said caller should have NREs thrown at them until the end of days. However, I'm much less sure about this than I am in native code land -- C# has quite a different programming style in places compared to either C or C++ in this regard.
So... should you check for null parameters in C# methods?
Yes, check for them. Preferably use Code Contracts to tell the caller that you require non-null parameters
void Foo(Bar bar) {
Contract.Requires(bar != null);
}
This is particularly advantageous since the client can see exactly what is required of parameters.
If you can't use Code Contracts, use a guard clause
void Foo(Bar bar) {
Guard.Against<ArgumentNullException>(bar == null);
}
Fail fast.
I think it's better to throw an ArgumentNullException
(or use a contract as Jason suggests) if your method doesn't want a particular parameter to be null. It's a much better indicator by the contract to the client not to pass null in the first place when calling your method.
Null-checking is then the client's responsibility which makes for more maintainable code on both sides (often a win-win situation)... at least that's what I feel.
It is a good practice to validate all the parameters at least in public methods. This helps to locate bugs faster and also helps while reading the code, as it describes method's contract.
We implemented a static class AssertUtilities
that has a bunch of method for parameters and state validation. I believe some people call such classes Guard
.
For example:
public static void ArgumentNotNull(object argument, string argumentName)
{
if (argument == null)
throw new ArgumentNullException(argumentName);
}
public static void ArgumentInRange(decimal argument, decimal minValue, decimal maxValue, string argumentName)
{
if (argument < minValue || argument > maxValue)
{
throw new ArgumentOutOfRangeException(
argumentName,
FormatUtilities.Format("Argument out of range: {0}. Must be between {1} and {2}.", argument, minValue, maxValue));
}
}
public static void ArgumentState(bool expression, string argumentName, string formatText, params object[] args)
{
if (!expression)
throw new ArgumentException(FormatUtilities.Format(formatText, args), argumentName);
}
public static void ArgumentHasText(string argument, string argumentName)
{
ArgumentNotNull(argument, argumentName);
ArgumentState(argument.Length > 0, argumentName, "Argument cannot be an empty string.");
}
So... should you check for null parameters in C# methods?
Yes, unless of course when null
is permitted.
A better perspective: You should always check for valid parameter values. Sometimes a reference is allowed to be null, sometimes an int
must be >= 0
or a string may not be NullOrWhiteSpace.
So it is a good practice to start every method with a parameter validation block.
From there on there are a few choices. Validation on internal/private methods is usually considered less critical, and for performance reasons it can be made conditional (or even left out).
Validation at a boundary is usually left on in Release builds. There is very little reason to ever turn it off.
Most projects will use some helper classes for validation, to minimize repetitive coding inside the methods. A very good but not yet very popular toolkit is the built-in System.Diagnostics.Contracts class. The Code-Contracts tools have many settings concerning parameter validation.
精彩评论