.NET, Archive, C#
     

Tail Recursion Revisited

A year ago I blogged about Tail Recursion in C# on .NET 2.0. With the public beta of .NET 3.5 now available, I decided to retry my little experiment.

For the experiment I used Beta 1 of .NET 3.5 (version 3.5.20404), which you can get from here. Using the supplied compiler, I compiled the following C# code:

public class TailTest{
	public static void Main(){
		TailTest f = new TailTest();
		f.DoTail(0);
	}
	public void DoTail(int n){
		int v = n + 1;
		System.Console.WriteLine(v);
		DoTail(v);
	}
}

Just running the produced EXE is enough to determine that even with the newest version of Microsoft’s compiler, the program has not been optimized for tail recursion. Just to confirm this findings, I went ahead and decompiled the EXE to IL anyway.

.class public auto ansi beforefieldinit TailTest
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: call instance void [mscorlib]System.Object::.ctor()
        L_0006: ret 
    }

    .method public hidebysig instance void DoTail(int32 n) cil managed
    {
        .maxstack 2
        .locals init (
            [0] int32 num)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: ldc.i4.1 
        L_0003: add 
        L_0004: stloc.0 
        L_0005: ldloc.0 
        L_0006: call void [mscorlib]System.Console::WriteLine(int32)
        L_000b: nop 
        L_000c: ldarg.0 
        L_000d: ldloc.0 
        L_000e: call instance void TailTest::DoTail(int32)
        L_0013: nop 
        L_0014: ret 
    }

    .method public hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 2
        .locals init (
            [0] class TailTest test)
        L_0000: nop 
        L_0001: newobj instance void TailTest::.ctor()
        L_0006: stloc.0 
        L_0007: ldloc.0 
        L_0008: ldc.i4.0 
        L_0009: callvirt instance void TailTest::DoTail(int32)
        L_000e: nop 
        L_000f: ret 
    }

}

From my previous discussion, we can see that the resulting IL lacks the “tail.”. With all the innovation in C# for the upcoming release of .NET 3.5, I was hoping that the outcome from my experiment would have been different.

Never miss an article! Subscribe to my newsletter and I'll keep you updated with the latest content.

 

About Jason

Jason is an experienced entrepreneur & software developer skilled in leadership, mobile development, data synchronization, and SaaS architecture. He earned his Bachelor of Science (B.S.) in Computer Science from Arkansas State University.
View all posts by Jason →

Leave a Reply

Your email address will not be published. Required fields are marked *