Friday, September 21, 2007

Boxing Mystery in Overloaded and Overridden Method

Recently I have produced a code with strange behaviour in my real C# project. Look at this code:

class BaseMystery

{

  public virtual void Foo(int i) { }

}

 

class Mystery : BaseMystery

{

  private void Foo(object i)

  {

    Console.WriteLine("Finished.");

  }

 

  public new void Foo(int i)

  {

    Foo(i);

  }

}

 

static void Main(string[] args)

{

  Mystery mystery = new Mystery();     

  mystery.Foo(3);

}


It produces:

Process is terminated due to StackOverflowException.


There is nothing strange. The method Mystery.Foo(int) is called repeatedly. Then I replaced hidding method Mystery.Foo(int) by overriding method:

class BaseMystery

{

  public virtual void Foo(int i) { }

}

 

class Mystery : BaseMystery

{

  private void Foo(object i)

  {

    Console.WriteLine("Finished.");

  }

 

  public override void Foo(int i)

  {

    Foo(i);

  }

}

 

static void Main(string[] args)

{

  Mystery mystery = new Mystery();     

  mystery.Foo(3);

}


And the output is:

Finished.


Hah! What is the matter? Let us go to explore IL code of method Mystery.Foo(int):

public new void Foo(int)


.method public hidebysig instance void Foo(int32 i) cil managed

{

  .maxstack 8

  L_0000: nop

  L_0001: ldarg.0

  L_0002: ldarg.1

  L_0003: call instance void BoxingMystery.Program/Mystery::Foo(int32)

  L_0008: nop

  L_0009: ret

}


and

public override void Foo(int)


.method public hidebysig virtual instance void Foo(int32 i) cil managed

{

  .maxstack 8

  L_0000: nop

  L_0001: ldarg.0

  L_0002: ldarg.1

  L_0003: box int32

  L_0008: call instance void BoxingMystery.Program/Mystery::Foo(object)

  L_000d: nop

  L_000e: ret

}


Argument i has been boxed. Why? I would expect that the IL body of method Mystery.Foo(int) will be the same in new and override declaration but it is different. It is very strange behaviour of compiler. What is your explanation?

Overridded method in my real project was the right one. In addition, I renamed the methods, because my colleagues could be confused like me.

kick it on DotNetKicks.com

Monday, September 17, 2007

Launch NUnit Tests directly from Visual Studio and Debug

Launching tests directly from Visual Studio is very comfortable feature. Developers, who are familiar with test driven development, need to launch tests frequently, so this feature is necessary for them.

My favourite testing framework is NUnit. Tests in this framework are launched from external application with perfect GUI.

In this article I will demonstrate how to start external application from Visual Studio, e.g. NUnit GUI, and keep running debugger. Debugging NUnit tests is very significant advantage because standard GUI of NUnit framework does not support it.

So, suppose that you have created a class library project with the following NUnit test:

using System.IO;

using NUnit.Framework;

using NUnit.Framework.SyntaxHelpers;

 

namespace DirectNUnit

{

  [TestFixture]

  public class Tests

  {

    [Test]

    public void Test()

    {

      string combinedPath = Path.Combine(@"C:\Projects", @"HelloWorld");

      Assert.That(combinedPath, Is.EqualTo(@"C:\Projects\HelloWorld"));

    }

  }

}



Now, you want to start this test directly from Visual Studio and use some breakpoints in the test. You can do it without any VS plug-in, just edit project settings. Open Project | Properties | Debug and set values like this:



Enter Start external program and Command line arguments, that is the path to the assembly containing your test.

For launching NUnit GUI and debugging tests press F5.

kick it on DotNetKicks.com