Small sample of using Code Contracts
- modified:
- reading: 4 minutes
I had read about Code Contracts long time ago, but I didn’t see a reason to use contract instead of simple tests and argument's check with Exception's throws. Only now I’m trying to use them at real project. I didn’t see why I need to write:
``` Contract.RequiresInstead of like I did it before:
```csharp if (argument == null) throw new ArgumentNullException(“argument”); ```Couple of weeks ago I had reinstall my Windows 7 on my laptop (I bought SSD for my laptop). After I install ReSharper with Visual Studio 2010 after run I accidental choosed “Go to the metadata” instead of like usual “Go to Object Explorer” by Ctrl and Mouse Click. So when I clicked on some class of System.xxx (basic classes of .NET) I looked at source code of these classes and found that they are using Code Contracts. I thought this is why I need to understand why I need to use contracts in my code, so I started to use them in some small applications and tried to find some interesting case.
You can look at previous blog post and find that I used code contracts in this sample. Actually it was first using code contracts. If you don’t know how to start using code contract in your project: you should go to the Microsoft Research site, download last code contracts installer and better to download last Editor Extension as well. When you will do this, you will see two additional tabs in project properties window.
So, let's look at an example. We have class like this:
``` public sealed class HotKey { private IntPtr _handle; public HotKey(Window window) :this (new WindowInteropHelper(window)) { } public HotKey(WindowInteropHelper window) :this(window.Handle) { } public HotKey(IntPtr windowHandle) { _handle = windowHandle; } } ```In this class we are working with window’s handle, but we allow to create instance of this class not only with Handle as paramters, but with Window or WindowInteropHelper objects as well. What will happen if user will try to create new HotKey instance and put null instead of Window object (first constructor)? We will get Exception with message “Value cannot be null. Parameter name:window.”, this exception will throw constructor of type WindowInteropHelper. So it is good luck that we will get understandable message. But what about null instead of WindowInteropHelper (second constructor)? Try it. You will get NullReferenceException with message “Object reference not set to an instance of and object”. No good. How we can handle it? We can try to use separate method Initialize:
``` public sealed class HotKey { private IntPtr _handle; public HotKey(Window window) { if (window == null) throw new ArgumentNullException("window"); Initialize(new WindowInteropHelper(window).Handle); } public HotKey(WindowInteropHelper window) { if (window == null) throw new ArgumentNullException("window"); Initialize(window.Handle); } public HotKey(IntPtr windowHandle) { Initialize(windowHandle); } private void Initialize(IntPtr windowHandle) { _handle = windowHandle; } } ```Аnd also you can use contracts:
``` public sealed class HotKey { private IntPtr _handle; public HotKey(Window window) : this (new WindowInteropHelper(window)) { Contract.Requires(window != null); } public HotKey(WindowInteropHelper window) : this(window.Handle) { Contract.Requires(window != null); } public HotKey(IntPtr windowHandle) { _handle = windowHandle; } } ```Looks like that if you will pass null instead of WindowInteropHelper in second constructor you will get NullReferenceException again, because first will executed code in base constructor and next constructor’s body which we invoke. And R# tell us that we don’t need to check window!=null, because we used this variable before considering that it can not be null (I created bug in ReSharper Youtrack):
Actually contracts works before method execution, so we will see Precondition failed exception:
Also if you want to see ArgumentNullException instead of ContractException you can write:
``` public sealed class HotKey { private IntPtr _handle; public HotKey(Window window) : this (new WindowInteropHelper(window)) { Contract.RequiresOr:
``` public sealed class HotKey { private IntPtr _handle; public HotKey(Window window) :this (new WindowInteropHelper(window)) { if (window == null) throw new ArgumentNullException("window"); Contract.EndContractBlock(); } public HotKey(WindowInteropHelper window) : this(window.Handle) { if (window == null) throw new ArgumentNullException("window"); Contract.EndContractBlock(); } public HotKey(IntPtr windowHandle) { _handle = windowHandle; } } ```So all next code only with contracts!