Params and a single null

I discovered an interesting qwerk with the C# params keyword when using NSubstitute recently.

I had a class that has two constructors

public class ClassToBeMocked
{
    public ClassToBeMocked(string param1)
    {
        //do stuff
    }

    public ClassToBeMocked(string param1, string param2)
    {
        //do stuff
    }
}

Now using NSubstitute I can mock these classes as such.

[Test]
public void MockMultipleParams()
{
    var mockInstance = Substitute.For<ClassToBeMocked>(null, null);
}

[Test]
public void MockSingleParam()
{
    var mockInstance = Substitute.For<ClassToBeMocked>(null);
}

The interesting thing is that the multiple params test works but the single param test fails with "Could not find a parameterless constructor."

So this puzzled me for a while until I took a guess and write the test like this

[Test]
public void MockSingleParamWithArray()
{
    Substitute.For<ClassToBeMocked>(new object[] {null});
}

Or

[Test]
public void MockSingleParamWithCast()
{
    Substitute.For<ClassToBeMocked>((object)null);
}

And both of these work. So it seems Substitute.For is just passing the params array directly to castle when building the proxy. This results in a null reference.

But why is this the case?

Well these is an interesting edge case when dealing with the params keyword and a single null. It is probably best illustrated with a simple code proof.

[TestFixture]
public class ParamsProof
{
    [Test]
    public void TestMethod()
    {
        MethodWithParams("one", "two");
        MethodWithParams("one");
        MethodWithParams();
        MethodWithParams(null, null);
        MethodWithParams((object)null);
        MethodWithParams(new object[]{null});
        MethodWithParams(null);
    }

    static void MethodWithParams(params object[] parameters)
    {
        if (parameters == null)
        {
            Debug.WriteLine("parameters is null");
            return;
        }

        Debug.WriteLine("parameters length is " + parameters.Length);
    }
}

and the output of this will be

parameters length is 2
parameters length is 1
parameters length is 0
parameters length is 2
parameters length is 1
parameters length is 1
parameters is null

As you can see a single null is interpreted as a null array, not an array containing a single null.

Here is the code http://code.google.com/p/simonsexperiments/source/browse/#hg%2FParamsAndASingleNull

Posted by: Simon Cropp
Last revised: 28 Dec, 2011 02:08 AM History

Comments

No comments yet. Be the first!

No new comments are allowed on this post.