Reputation: 282895
Off the top of my head, I can think of 4 ways to check for null arguments:
Debug.Assert(context != null);
Contract.Assert(context != null);
Contract.Requires(context != null);
if (context == null) throw new ArgumentNullException("context");
I've always used the last method, but I just saw a code snippet that used Contract.Requires
, which I'm unfamiliar with. What are the advantages/disadvantages of each method? Are there other ways?
In VS2010 w/ Resharper,
Contract.Assert
warns me that the expression is always true (how it knows, I'm not quite sure... can't HttpContext be null?), Contract.Requires
gets faded out and it tells me the compiler won't invoke the method (I assume because of the former reason, it will never be null), and context != null
all the code following gets faded out and it tells me the code is heuristically unreachable. So, it seems the last 3 methods have some kind of intelligence built into the VS static checker, and Debug.Assert
is just dumb.
Upvotes: 17
Views: 3946
Reputation: 27505
My guess is that there is a contract applied to the interface IHttpHandler.ProcessRequest which requires that context != null. Interface contracts are inherited by their implementers, so you don't need to repeat the Requires. In fact, you are not allowed to add additional Requires statements, as you are limited to the requirements associated with the interface contract.
I think it's important to make a distinction between specifying a contractual obligation vs. simply performing a null check. You can implement a null check and throw an exception at runtime, as a way to inform the developer that they are using your API correctly. A Contract expression, on the other hand, is really a form of metadata, which can be interpreted by the contract rewriter (to introduce the runtime exceptions that were previously implemented manually), but also by the static analyzer, which can use them to reason about the static correctness of your application.
That said, if you're working in an environment where you're actively using Code Contracts and static analysis, then it's definitely preferable to put the assertions in Contract form, to take advantage of the static analysis. Even if you're not using the static analysis, you can still leave the door open for later benefits by using contracts. The main thing to watch out for is whether you've configured your projects to perform the rewriting, as otherwise the contracts will not result in runtime exceptions as you might expect.
To elaborate on what the commenters have said, the difference between Assert, Assume and Requires is:
Upvotes: 12
Reputation: 67223
The first method is appropriate for testing for a null condition that should never exist. That is, use it during development to ensure it doesn't unexpectedly get set to null. Since it doesn't do any error handling, this is not appropriate for handling null conditions in your released product.
I would say the 2nd and 3rd versions are similar in that they don't handle the issue in any way.
In general, if there's a possibility that the variable could actually be null in the final product, the last version is the one to use. You could do special handling there, or just raise an exception as you've done.
Upvotes: 2