About 6 months ago, I briefly tried out JetBrains IntelliJ. As far as Java development goes, there doesn't appear to be a more impressive IDE. I had heard of JetBrains ReSharper for Visual Studio at that point but I hadn't tried it out. Needless to say, once you've given ReSharper a go there's just no going back.

When the ReSharper 4.0 EAP was announced I started testing it out. I did my bit for JetBrains and submitted bug reports when issues popped up. When it was finally released, I ordered my copy.

ReSharper 4.0 is packed with useful features. One of the new features that caught my eye is the Annotated Framework. On its own, the Annotated Framework doesn't appear as significant as the many other features provided. It's the last feature documented right down at the bottom of the Code Analysis feature page on the JetBrains site. But in terms of software development practices, it's an interesting indication of what direction JetBrains see developers taking to improve the quality of their code.

What is the Annotated Framework?

The Annotated Framework is contained in the JetBrains.Annotations namespace and consists of the following custom attributes (as described on the JetBrains web site).

  • StringFormatMethodAttribute (for methods that take format strings as parameters)
  • InvokerParameterNameAttribute (for methods with string literal arguments that should match one of caller parameters)
  • AssertionMethodAttribute (for assertion methods)
  • AssertionConditionAttribute (for condition parameters of assertion methods)
  • TerminatesProgramAttribute (for methods that terminate control flow)
  • CanBeNullAttribute (for values that can be null)
  • NotNullAttribute (for values that can not be null)

The idea is that you use these attributes to decorate your methods and parameters so that ReSharper can provide you with better live code analysis. For example, the code below shows a custom method called MyFormat that has the same signature as String.Format. This method uses composite formatting which means it takes a string that contains any number of format items (like {0}, {1}, etc.) in addition to that many parameters, each of which corresponds to a format item.

[StringFormatMethod("text")]
public void MyFormat( [NotNull] string text, params object[] args )
{
    // Output the text specified.
}

The method signature above is decorated with some attributes from the JetBrains.Annotation namespace. The first is a method attribute, StringFormatMethod and it takes a single parameter. The parameter is used to specify the name of the parameter in the method call that contains the composite format string. In this case, the string is called "text". The second is a parameter attribute, NotNull. This attribute is used to indicate that the parameter it decorates should never be null.

When you make calls to the MyFormat method, ReSharper will inform you of any instances where your code is not complying with the requirements of these attributes. Below is a usage example.

public void TestMethod()
{
    int i = 0;
    int j = 0;
 
    // The call to MyFormat below is flagged by ReSharper as containing problems
    // because it has two format items, but only one additional paramter.
    MyFormat( "{0}, {1}", i );
 
    // The call to MyFormat below is flagged by ReSharper as containing problems
    // because the composite format string parameter is null.
    MyFormat( null, i, j );
    
    // The call to MyFormat below is not flagged because the composite format string 
    // is not null and both format items are accounted for in the parameters i and j.
    MyFormat( "{0}, {1}", i, j );
}

In addition to being able to use these attributes in your own code, JetBrains have annotated most of the .NET Framework so you get a nice benefit there also.

To use the code annotation attributes in your own code, you can either add a reference to the JetBrains.Annotations.dll (found in the ReSharper install directory) or, copy the default implementation straight into your project.

The key point to keep in mind about the Annotated Framework is that it is designed to give you better code analysis. There are no runtime implications here, in other words no exceptions will be thrown if a parameter you've annotated with the NotNullAttribute ends up containing a null value.

But wouldn't it be nice if the Annotated Framework did allow you to enforce runtime constraints? Spec# (from Microsoft Research) has this facility and more. Check Scott Hanselman's podcast on Spec# for more info.

As it is the Annotated Framework looks like a step towards Design by Contract for C# developers.

Design by Contract

According to Wikipedia, Design by Contract is an approach to software design whereby 'software designers should define precise verifiable interface specifications for software components based upon the theory of abstract data types and the conceptual metaphor of a business contract.'

For a method on a class object, this boils down to the following.

  1. Specifying a precondition for the method. The caller of the method is obliged to meet this precondition and this frees the method from having to handle the precondition.
  2. Specifying a postcondition for the method. The method will guarantee this postcondition on exit. This frees the caller from having to handle the postcondition.
  3. Specifying an invariant. The method assumes this value on entry and guarantees it on exit.

The extent to which C# currently supports Design By Contract natively is type checking. For example, the code below shows a method that allows the caller to set an email address.

public void SetEmail( string email )
{
    // Store the email address.    
}

The contract being enforced by C# natively for this method guarantees that the email parameter must be a string object. But an email address is more than just a string. It's a string that contains characters in a specific pattern. In the code below I've made the contract less vague with a fictitious Regex attribute.

public void SetEmail( [Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*")] string email )
{
    // Store the email address.
}

In the code above I've made the contract explicit. It implies that the method should only accept strings that contain valid email addresses that match the specified regular expression for an email address. This requirement is not buried inside the method body.

I've read some interesting blog posts recently describing different approaches to enforcing contracts as described above. Fredrik Normén and Roger Alsing have both written about this topic.

Extending the Annotated Framework

As a test, I decided to try and extend the annotated framework so that it also provides run-time checking. There are a number of difficulties with the idea of enforcing contracts with attributes at run-time using the current version of C#. Although you can use reflection to get details about the parameters of a method, it is not possible to use this approach to retrieve the value of these parameters at run-time. If you could get at these values easily it would mean you could decorate your methods to describe a contract and then assert the contract with a simple call to an contract method as shown below.

public void SetEmail([Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*")] string email)
{
    Contract.Demand();
    
    // Continue with method body
}
 
public static class Contract
{
    public static void Demand()
    {
        var stack = new StackTrace(false);
        var frame = stack.GetFrame(1);
        var method = frame.GetMethod();
 
        foreach (var parameter in method.GetParameters())
        {
            foreach (var attribute in parameter.GetCustomAttributes(false))
            {
                var validator = attribute as ValidatorAttribute;
                if( validator != null)
                {
                    validator.Validate(parameter.Name, parameter.Value); // NOTE: parameter.Value is a fictitious property.
                }
            }
        }
    }
}

The code above assumes that all Custom Validation Attributes derive from a ValidatorAttrbiute class whose interface contains a method called Validate. It also uses a fictitious property of the ParameterInfo object parameter.

To get the above code to compile and run, I had to pass in the parameter values and remove the reference to the fictitious ParameterInfo Value property as shown below.

public void SetEmail([Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*")] string email)
{
    Contract.Demand( email ); // Pass in the method parameters.
 
    // Continue with method body        
}
 
public static class Contract
{
    public static void Demand(params object[] parameters)
    {
        var stack = new StackTrace(false);
        var frame = stack.GetFrame(1);
        var method = frame.GetMethod();
 
        var parameterIndex = 0;
        foreach (var parameter in method.GetParameters())
        {
            foreach (var attribute in parameter.GetCustomAttributes(false))
            {
                var validator = attribute as ValidatorAttribute;
                if( validator != null)
                {
                    validator.Validate(parameter.Name, parameters[parameterIndex]);
                }
            }
            parameterIndex++;
        }
    }
}

This requires that all the parameters appear in the call to Contract.Demand, and they must occur in the same order as the containing method. Apart from the performance issues that come with using reflection, the approach I've tested above is just not as clean as other simpler approaches to contract validation. And it doesn't come close to what can be done with Spec#.

Conclusion

The new ReSharper Annotated Framework does exactly what it's supposed to. It improves code analysis. It also encourages a Design by Contract approach to software development. In effect, it offers a first line of defense against vague interfaces and focuses the developer on establishing expectations before and after method calls. It will be interesting to see if, or how this influences the C# community in general and also how this in turn influences Microsoft when advancing the C# language. Let's hope that Microsoft Research get the chance to have Spec# improvements integrated into C#.

You can find out more about ReSharper 4.0 at the JetBrains web site.


My first experience with the .NET Framework was co-writing a custom build system in C# a few years ago. The build system ran as an add-in for Visual Studio 2003 and 2005. It enabled the developer to port a single code/content base to any number of Java ME and Brew handsets.

The core build system was pretty straight forward, but we ran in to some problems with the .NET Process object. Each step of the build system was executed as either an internal command, or an external process. The external processes were kicked off using the .NET Process object. These external processes could kick off a single executable file. Or, they could run a batch file, potentially spawning several child processes.

Under normal operation this was completely fine. However, canceling a build half way through exposed some limitations of the .NET Process object.

It turns out that Win32 doesn't maintain a parent/child hierarchy of processes. Killing the parent process wont automatically kill the child processes. So, if you create a .NET Process object, and that object creates a child process, killing the parent process just orphans the child process.

Process Groups

Visual Studio 2003 ships with a command-line tool called VCSPAWN.EXE. This tool was designed to solve the above problem for console applications. It works by exploiting the fact that all console processes run in a console group. When a message is sent to the group, all processes in the group receive the message. Under the hood VCSPAWN.EXE ensures that each process it spawns belongs to the same group. Terminate VCSPAWN.EXE and you terminate any processes it has spawned.

This is a good solution but VCSPAWN.EXE does not ship with Visual Studio 2005 or 2008.  Also, it does not handle GUI applications as far as I know.

Job Objects

Windows 2000 (and up) provide Job Kernel Objects. Job Kernel Objects offer a much better solution to the above problem, allowing you to group several processes together. Terminate the Job Object and all processes assigned to the Job Object are terminated also. This works for child processes because child processes are automatically assigned to the same job as the parent process.

There's one problem. The .NET Framework does not expose Job Kernel Objects as standard so we have to use Interoperation (specifically P/Invoke) to use this functionality. Below is some code that shows how to use a Job Object to run a .NET Process object. The idea is simple. Create your process in a suspended state. Assign it to a Job Object. Then, to terminate the process and all child processes, just terminate the Job Object.

class JobObjectProcess
{
    protected Process _process;
    protected IntPtr _jobHandle;
 
    public JobObjectProcess(ProcessStartInfo startInfo)
    {
        _process = new Process();
        _process.StartInfo = startInfo;
 
        CreateJobObject();
    }
 
    private void CreateJobObject()
    {
        win32.SECURITY_ATTRIBUTES SA = new win32.SECURITY_ATTRIBUTES();
        SA.nLength = 12;
        SA.SecurityDescriptor = IntPtr.Zero;
        SA.bInheritHandle = true;
        _jobHandle = win32.CreateJobObject(ref SA, "");
    }
 
    public bool Start()
    {
        bool started = _process.Start();
 
        if (started)
        {
            bool success = win32.AssignProcessToJobObject(_jobHandle, _process.Handle);
            if (!success)
            {
                string error = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                throw new ApplicationException(error);
            }
        }
 
        return started;
    }
 
    public void Kill()
    {
        bool success = win32.TerminateJobObject(_jobHandle, 0);
        if (!success)
        {
            string error = new Win32Exception(Marshal.GetLastWin32Error()).Message;
            throw new ApplicationException(error);
        }
 
        if (_jobHandle != IntPtr.Zero)
        {
            if (0 == win32.CloseHandle(_jobHandle))
            {
                string error = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                throw new ApplicationException(error);
            }
            _jobHandle = IntPtr.Zero;
        }
    }
}

There's a problem with the code above. It starts the .NET Process object before it assigns it to the Job Object. For processes that don't exit quickly this is fine. But for processes that terminate quickly we could still end up with orphaned child processes. So why not just start the process suspended like I mentioned earlier? Well, the .NET Framework Process object doesn't expose a way to do this.

The only way around this is to use interoperation to call CreateProcess to create a process in a suspended state. The good news is this works fine. On Windows XP.

Vista

It doesn't work on Windows Vista due to the enhanced security features. Luckily, there is also a way around this. In order to get this to work on Vista I had to replace the CreateProcess call with a call to CreateProcessAsUser. This call will create a process under the security token that is specified as a parameter. This token must be a primary token. I used the DuplicateTokenEx API method to convert the token of the current user to a primary token. The process is then created in a suspended state and assigned to a Job Object. Finally the main process thread is resumed. For more information on how CreateProcessAsUser is being used in this context, see this article.

If you want to know more about Job Kernel Objects, Jeffrey Richter has written several articles on this subject. You can find out more here and here.

Below is the C# source code for the custom JobObjectProcess object. Calling Kill on the JobObjectProcess will terminate the parent process and any child processes it has spawned.

[Update: For a much more complete solution that uses Job Objects in managed code, check the JobObjectWrapper up on CodePlex.]

class JobObjectProcess
{
    private IntPtr _jobHandle;
 
    public JobObjectProcess()
    {
    }
 
    public bool Start(string commandLinePath)
    {
        IntPtr Token = new IntPtr(0);
        IntPtr DupedToken = new IntPtr(0);
        bool ret;
 
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.bInheritHandle = false;
        sa.Length = Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = (IntPtr)0;
 
        Token = WindowsIdentity.GetCurrent().Token;
        const uint GENERIC_ALL = 0x10000000;
        const int SecurityImpersonation = 2;
        const int TokenType = 1;
        ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
 
        STARTUPINFO si = new STARTUPINFO();
        si.cb = Marshal.SizeOf(si);
        si.lpDesktop = "";
 
        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        const int CREATE_SUSPENDED = 0x00000004;
        ret = CreateProcessAsUser(DupedToken, null, commandLinePath, ref sa, ref sa, false, CREATE_SUSPENDED, (IntPtr)0, "c:/", ref si, out pi);
 
        SECURITY_ATTRIBUTES saJob = new SECURITY_ATTRIBUTES();
        saJob.Length = 12;
        saJob.lpSecurityDescriptor = IntPtr.Zero;
        saJob.bInheritHandle = true;
        _jobHandle = CreateJobObject(ref saJob, "");
 
        bool success = AssignProcessToJobObject(_jobHandle, pi.hProcess);
        int nSuspendCount = ResumeThread(pi.hThread);
 
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        CloseHandle(DupedToken);
 
        return true;
    }
 
    public bool Kill()
    {
        bool success = TerminateJobObject(_jobHandle, 0);
        CloseHandle(_jobHandle);
        return success;
    }
 
    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public int cb;
        public String lpReserved;
        public String lpDesktop;
        public String lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
 
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }
 
    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int Length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }
 
    [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public extern static bool CloseHandle(IntPtr handle);
 
    [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
        String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
 
    [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
    public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
        ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
        int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
 
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr CreateJobObject(ref SECURITY_ATTRIBUTES JobAttributes,
        [MarshalAs(UnmanagedType.LPTStr)]string strName);
 
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
 
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool TerminateJobObject(IntPtr hJob, uint exitCode);
 
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int ResumeThread(IntPtr hThread);
}