Tag Archives: Visual Basic

Change the runtime of an IIS 7 application pool

The following quick SDK sample demonstrates how to list and change the managed runtime version of application pools programatically in IIS 7.

[VB]

Imports System
Imports Microsoft.Web.Administration
Public Class AppPoolSample
 Shared manager As ServerManager = New ServerManager()
  ' Main application processing
  Public Shared Sub Main(ByVal args As String())
      ' Get the apppool to change
      Dim iPool As Integer = GetAppPool()
      ' Get the framework version desired
      Dim rtVersion As String = GetVersion()
      ' Set the apppool runtime
      Dim poolToSet As ApplicationPool = manager.ApplicationPools(iPool)
      Console.WriteLine(
            "Setting application pool '{0}' to runtime version: {1}...", _
            poolToSet.Name, rtVersion)
      poolToSet.ManagedRuntimeVersion = rtVersion
      ' Commit the changes and recycle the application pool
      manager.CommitChanges()
      poolToSet.Recycle()
      Console.WriteLine("Your changes have been committed.")
  End Sub

  ' Prompts the user to select an application pool
  Public Shared Function GetAppPool() As Integer
    Dim pool As String = String.Empty
    Dim iPool As Integer = 0
    While (Not Integer.TryParse(pool, iPool))
      Console.WriteLine("Available ApplicationPools: Managed runtime version")
      Dim i As Integer
      For i = 0 To manager.ApplicationPools.Count - 1 Step i + 1
        Dim appPool As ApplicationPool = manager.ApplicationPools(i)
        Console.WriteLine("{3}{0,3}.{3}{1}: {2}", i + 1, _
            appPool.Name, appPool.ManagedRuntimeVersion, vbTab)
      Next
      Console.Write("{0}Choose an application pool to change: ", vbCrLf)
      pool = Console.ReadLine()
    End While
    Return iPool - 1
  End Function

    ' Prompts a user to select the version of runtime they would like
    ' the application pool to use
    Public Shared Function GetVersion() As String
        Dim rtVersion As String = String.Empty
        Dim iVersion As Integer = 0
        While (Not Integer.TryParse(rtVersion, iVersion))
            Console.WriteLine("{0}  1.{0}Framework version 1.0", vbTab)
            Console.WriteLine("{0}  2.{0}Framework version 1.1", vbTab)
            Console.WriteLine("{0}  3.{0}Framework version 2.0", vbTab)
            Console.Write("Choose the new managed runtime version: ")
            rtVersion = Console.ReadLine()
        End While
        Select Case iVersion
            Case 1
                rtVersion = "v1.0"
            Case 2
                rtVersion = "v1.1"
            Case 3
                rtVersion = "v2.0"
        End Select
        Return rtVersion
    End Function
End Class

[C#]

using System;
using Microsoft.Web.Administration;

public class AppPoolSample 
{
  static ServerManager manager = new ServerManager();
  // Main application processing
  public static void Main(string[] args)  
  {
    // Get the apppool to change
    int iPool = GetAppPool();
    // Get the framework version desired
    string rtVersion = GetVersion();
    // Set the apppool runtime
    ApplicationPool poolToSet = manager.ApplicationPools[iPool];
    Console.WriteLine(
        "Setting application pool '{0}' to runtime version: {1}...",
        poolToSet.Name, rtVersion);
    poolToSet.ManagedRuntimeVersion = rtVersion;
    // Commit the changes and recycle the application pool
    manager.CommitChanges();
    poolToSet.Recycle();
    Console.WriteLine("Your changes have been committed.");
  }
  // Prompts the user to select an application pool
 public static int GetAppPool()
 {
    string pool = String.Empty;
    int iPool = 0;
    while ((!int.TryParse(pool, out iPool)) ||
            (iPool > manager.ApplicationPools.Count || iPool <= 0))
    {
      Console.WriteLine(
                    "Available ApplicationPools: Managed runtime version");
      for (int i = 0; i <= manager.ApplicationPools.Count - 1; i++)
      {
        ApplicationPool appPool = manager.ApplicationPools[i];
        Console.WriteLine("t{0,3}.t{1}: {2}", i + 1, 
            appPool.Name, appPool.ManagedRuntimeVersion);
      }
      Console.Write("rnChoose an application pool to change: ");
      pool = Console.ReadLine();
  }
  return iPool -1;
}
  // Prompts a user to select the version of runtime they would like
  // the application pool to use
  public static string GetVersion()
  {
    string rtVersion = String.Empty;
    int iVersion = 0;
    while ((!int.TryParse(rtVersion, out iVersion)) ||
            (iVersion > 3 || iVersion < 1))
    {
      Console.WriteLine("rnt   1.tFramework version 1.0");
      Console.WriteLine("t   2.tFramework version 1.1");
      Console.WriteLine("t   3.tFramework version 2.0");
      Console.Write("Choose the new managed runtime version: ");
      rtVersion = Console.ReadLine();
    }
    switch (iVersion)
    {
        case 1:
            rtVersion  = "v1.0";
            break;
        case 2:
            rtVersion = "v1.1";
            break;
        case 3:
            rtVersion = "v2.0";
            break;
    }
    return rtVersion;
  }
}

Online Training: Beginners Guide to VB.NET

Microsoft Learning has put together a great series of training courses which are available now at a substantial discount.  Take advantage of the deal while it lasts (sale ends June 30th)!

https://www.microsoftelearning.com/visualstudio2005/#upgradingfromVB60

Also, don’t forget to check out the free training videos for VB.NET Express Edition. They provide a great starting point for anyone looking to break into the Visual Basic .NET market.

http://msdn.microsoft.com/vstudio/express/vb/learning/

Threading issue with VB.NET Default Instances

Here is an issue that showed up for one of our customers in the Microsoft forums for Visual Basic .NET.  It is NOT the typical ”cross-threaded UI update” issue that you might think. No, this one, IMO, is slightly harder to catch since no exception is thrown to let you know something has gone wrong.

One of the many new features of Visual Basic .NET are default form instances.  As the feature lists explain, a default form instance prevents you from having to “new up” an instance of a form before acting on it.  So, instead of using:

Dim frm As New frmMain
frm.Show()

I can simply use:

frmMain.Show()

This is handy, particularly for the folks coming from VB6 who are used to forms that behave in this manner.  However, default instances present a very interesting problem.

Take, for instance, a project that I create with a form (named frmMain) and a module (named BackgroundMethods.vb) .  For the form, I have simply added a multi-line text box (named txtOutput) and a button control (named button1). 

Here is the code I have in my project:

[frmMain]

Imports System.Threading
Public Class frmMain
  Private Sub Button1_Click( ByVal sender As System.Object, _
                             ByVal e As System.EventArgs) _
                             Handles Button1.Click
     Dim t As Thread = New Thread(AddressOf GetData)
     t.Start()
     txtOutput.Text &= "Updates complete"
     ' Break after the call above to read the value
     ' in txtOutput.Text
  End Sub
End Class

[BackgroundMethods.vb]

Imports System.Threading
Module BackgroundMethods
   Public Sub GetData()
      WaitForData("Message 1")
      WaitForData("Message 2")
   End Sub
   Public Sub WaitForData(ByVal strMessage As String)
      ' Presumably this method would actually be
      ' waiting for data from a network connection,<
      ' serial port, or other source
      Thread.Sleep(2000)
      My.Forms.frmMain.txtOutput.Text &= (vbCrLf & Now().ToShortTimeString() & _
      vbTab & strMessage)
      ' Break after the call above to read the value
      ' in My.Forms.frmMain.txtOutput.Text
   End Sub
End Module

So the simple example is that I have a button which, when clicked, will execute the “GetData” method asynchronously in a module.  That method is going to call the WaitForData method that updates the UI with two different messages (“message1” and “message2”).  WaitForData is supposed to simulate a long-running process, so I threw in the typical “thread.sleep” call to make this illusion. 

If you run this code, you will notice that no exceptions are thrown, but the UI for your form is also not updated.  Why is this?  You would have at least expected a cross-thread exception, right?

In any other managed language, this likely wouldn’t happen — namely because the “My” application is specific to VB, as well as default form instances!  In C#, if I try to update the UI from another thread, I would get an exception stating: “Cross-thread operation not valid: Control ‘txtSerialIn’ accessed from a thread other than the thread it was created on.” which could be solved by using the “Invoke” method.   

The issue with Visual Basic, in this instance, is that the default form instances are thread-specific.  So, when I try to access the form using My.Forms.frmMain from within the worker thread, a NEW default instance is created under the covers.  My calls to update the text box are then executed on the NEW instance of the form which resides in the same thread as the call to update it — hence it doesn’t throw a cross-thread exception. In the mind of the VB program, the request to update the textbox occurred without an error.  When the worker thread dies, the second instance of the form (which was never displayed) is now a candidate for garbage collection.  Meanwhile, back on the original thread and original form the textbox is left blank.  You can validate this by running the program (I have attached sample code to this blog post) and setting breakpoints on the textbox update line in the WaitForData method, and in the last line of the button1_click event handler of the code.  You will notice that after the second call to WaitForData (before the debugger exits the Sub) that My.Forms.frmMain.txtOutput.Text has been properly set to the value you expected.  However, remember that this is on a second background instance of the form, not the original one you expected.  Once the debugger hits the last line in the button1_click event handler, read the value of txtOutput.Text and realize THAT instance of the textbox was never updated.

So what is the solution?

First off, you still have to use the “Invoke solution” that is often times bandied about in threading discussions.  To do this in VB.NET (and particularly in our solution), do the following:

1. Add the following code to the top of your BackgroundMethods.vb file:

Delegate Sub UpdateTextHandler(ByVal strMessage As String

This allows you to create a delegate that can be invoked on the UI.

2. Add the following method to your frmMain file:

Public Sub UpdateTextMethod(ByVal strMessage As String)
   txtOutput.Text &= (vbCrLf & Now().ToShortTimeString() & vbTab & strMessage)
End Sub

This creates the method that will actually be executed via your delegate from the worker thread.

3. Change your WaitForData method as follows:

Public Sub WaitForData(ByVal strMessage As String)
    ' Presumably this method would actually be
    ' waiting for data from a network connection
    ' serial port, or other source
    Thread.Sleep(2000)
    Dim f As frmMain = My.Application.OpenForms("frmMain")
    f.Invoke(New UpdateTextHandler(AddressOf f.UpdateTextMethod), _
             New Object() {strMessage})
End Sub

This method now uses the form’s “Invoke” method (actually defined in Control) to execute UpdateTextMethod on the original form via the UpdateTextHandler delegate.

So what is happening is that your new thread is getting an instance to the existing frmMain instance by going through the OpenForms call.  Once I have that instance, I can invoke a delegate that points to the “UpdateTextMethod” of the existing form ( passing in the message in the object array ).  By invoking, I am able to get back on the UI’s thread and that call can execute any updates to the UI that it wishes.

Keep this in mind the next time you are not receiving errors and your UI isn’t getting updated how you would expect — particularly if you code communicates with the network, a serial device, or other device which communicates asynchronously.

Free Book: Microsoft VB.NET 2005 for Developers

Microsoft has a free book available for download for anyone who wants it.  Download the whole book, or download it chapter-by-chapter (8 in all).  Check it out at http://msdn.microsoft.com/vbasic/learning/introtovb2005/

202 VB.NET Samples

I just wanted to bring some attention to a resource that I think is extremely valuable for VB developers (and really, any .NET developer using any other language for that matter).  MSDN has a website with 101 Code Samples for VB.NET 2005.  There is also another website for those of you that haven’t upgraded to 2005 yet: 101 Code Samples for VB.NET 2003.  Both of these sites have very valuable sample code for doing things such as network programming, using regular expressions, executing transactions, handling/changing ACL’s on files, accessing data, performing bulk data transactions, executing asynchronous operations (one of my favorite topics), using ClickOnce, creating ASP.NET pages and more!  It is a great resource for those of you that just want to get it done and don’t want to waste a lot of time reading specifications on each class in System.Net or System.Data.  The samples are robust and provide some great starting points for anyone interested in the many topics available in these samples.  Check them out and let me know what you think!

Overrides vs Shadows keywords in VB.NET

When most folks come from a VB 6 background (and only VB6) they tend not to quite grasp object oriented programming right off the bat. Its one of the reasons why inheritance topics are fairly common on the Visual Basic .NET forums and newsgroups. Today was no different. I woke up and browsed the MSDN forums to find another such question. The user was asking what the difference between an Overridable method being overriden with the “Overrides” keyword, or an ordinary method being overriden by the “Shadows” keyword.

I decided to write a quick article about this and post it for future reference.

First off, lets define the similarities between these two keywords. Both Shadows and Overrides define a means to decorate our methods so we can redefine the functionality provided by a base class. So if I create a BaseClass, and then create a SubClass that inherits from BaseClass, its possible that I might want to redefine how the base and sub classes behave and interact with one another. While I can use either of these keywords, they are completely different in their orientation.

Let’s jump right into it by writing ourselves a base class. This class will have two methods — one that has an overridable method, and one that uses an ordinary method.

' BaseClass impliments an overridable and ordinary method
Public Class BaseClass
  Public Overridable Sub OverridableSub()
    Console.WriteLine(" BaseClass.OverridableSub() called")
  End Sub
  Public Sub OrdinarySub()
    Console.WriteLine(" BaseClass.OrdinarySub() called")
  End Sub
End Class

When you see the overridable keyword in a piece of Visual Basic code, it is an indicator that the designer of this class intended or expected that this class would be Subclassed (overridden) at some point and that “OverridableSub” was a likely candidate for functionality redefnition. You can also deduce that the designer didn’t intend for OrdinarySub to be overriden.

For a bit of advanced education, lets look at the IL produced by these methods.First off, the OrdinarySub looks like any other subroutine we’ve seen in IL before.

.method public instance void OrdinarySub() cil managed

We have a public instance method. Look what happens, however, with our OverridableSub method signature.

.method public newslot virtual instance void OverridableSub() cil managed

Notice we have two additional method characteristics added : virtual and newslot. The virtual characteristic should be familiar to most C# developers. It indicates that the item can be overridden. With that definition, it should now be obvious to VB.NET developers that this means the method has the Overridable modifier. The second characteristic is newslot which indicates that the method will always get a new slot on the object’s vtable. We’ll get into this more later.

So if we want to test our BaseClass, we might write a piece of code something like this in our Main method:

Module Module1
    Sub Main()
        ' Create an instance of the base class and call it directly
        Console.WriteLine("+ Calling BaseClass Methods")
        Console.WriteLine("--------------------------------------------------")
        Dim bc As New BaseClass
        bc.OverridableSub()
        bc.OrdinarySub()
        Console.ReadLine()
    End Sub
End Module

And of course executing this code we would get our exepcted results as follows:

+ Calling BaseClass Methods
--------------------------------------------------
   BaseClass.OverridableSub() called
   BaseClass.OrdinarySub() called
As you'll notice it states that we executed both of our methods against the BaseClass instance. Sounds great, now let's say we now want to create a class that inherits from BaseClass:

' SubClass impliments an overriden BaseClass with overrides and shadows modifiers
Public Class SubClass
    Inherits BaseClass

    Public Overrides Sub OverridableSub()
        Console.WriteLine("   SubClass.OverridableSub() called")
    End Sub
    Public Shadows Sub OrdinarySub()
        Console.WriteLine("   SubClass.OrdinarySub() called")
    End Sub
End Class

To be able to override both of these methods, and stop the compiler from barking at us, we needed to use the overrides keyword on our OverridableSub and the Shadows keyword on our OrdinarySub. This is obviously because of the way we have implemented these methods in the base class. Shadows is a fairly appropriate word because what we are doing is putting the original method (OrdinarySub) in the proverbial shadow of our new method. Our new method stands over top of the old method and executes any time we call against a direct instance of SubClass. Let’s exand our Main method to execute both our SubClass and our BaseClass to see what the difference is:

Module Module1
    Sub Main()
        ' Create an instance of the base class and call it directly
        Console.WriteLine("+ Calling BaseClass Methods")
        Console.WriteLine("--------------------------------------------------")
        Dim bc As New BaseClass
        bc.OverridableSub()
        bc.OrdinarySub()
        Console.WriteLine()

        ' Create an instance of the sub class and call it directly
        Console.WriteLine("+ Calling SubClass Methods ")
        Console.WriteLine("--------------------------------------------------")
        Dim sc As New SubClass
        sc.OverridableSub()
        sc.OrdinarySub()
        Console.WriteLine()
        Console.ReadLine()
    End Sub
End Module 

It follows that because we’ve overridden both of our methods our output would look as follows:

+ Calling BaseClass Methods
--------------------------------------------------
   BaseClass.OverridableSub() called
   BaseClass.OrdinarySub() called

+ Calling SubClass Methods
--------------------------------------------------
   SubClass.OverridableSub() called
   SubClass.OrdinarySub() called

We now are executing code that executes against a BaseClass instance, and we can tell by the output that we are calling the base class methods. We are also executing code against a SubClass instance and we can tell that this is executing our new functionality because the method states its executing SubClass.OverridableSub() and SubClass.OrdinarySub(), not BaseClass.OverridableSub() and BaseClass.OrdinarySub().OK, so we still haven’t seen a difference. Both of these methods really accomplished the same thing didn’t they? We had a base class behavior and both methods overrode that behavior with our newly created methods, right? True enough, but lets look at the consequential differences when we pass our reference around in different ways. We can see example after example in the framework where a method will take a parameter as a general type, but it really expects us to pass in a more specific type. For instance, if a parameter is typed as an XmlNode, we can pass in XmlElements, XmlAttributes, XmlConfigurationElement etc. The list goes on. Why can we do this? Because generally speaking, if I’m an XmlElement, I am also an XmlNode. An XmlElement is a more specific implementation of an XmlNode, so while the XmlElement has more functionality, it still has the base functionality provided by its inherited type XmlNode. So what happens if we create methods that takes BaseClass as a parameter and we pass in an instance of a SubClass as follows?

' Calls the OverridableSub method of the instance passed to it
Public Sub CallOverridableSub(ByVal instance As BaseClass)
    instance.OverridableSub()
End Sub

' Calls the OrdinarySub method of the instance passed to it
Public Sub CallOrdinarySub(ByVal instance As BaseClass)
    instance.OrdinarySub()
End Sub

Notice that we have too methods that both take an instance of BaseClass, not the more specific SubClass. Additionally, we are calling the OverridableSub() method in one of these methods, and OrdinarySub() in the other. Let’s add more code to our Main method to execute these methods passing in an instance of a SubClass. The full code for our example should look like this:

Module Module1
    Sub Main()
        ' Create an instance of the base class and call it directly
        Console.WriteLine("+ Calling BaseClass Methods")
        Console.WriteLine("--------------------------------------------------")
        Dim bc As New BaseClass
        bc.OverridableSub()
        bc.OrdinarySub()
        Console.WriteLine()

        ' Create an instance of the sub class and call it directly
        Console.WriteLine("+ Calling SubClass Methods ")
        Console.WriteLine("--------------------------------------------------")
        Dim sc As New SubClass
        sc.OverridableSub()
        sc.OrdinarySub()
        Console.WriteLine()

        ' Pass the SubClass instance to a method passed as a BaseClass reference
        Console.WriteLine("+ Calling SubClass Methods passed as BaseClass")
        Console.WriteLine("--------------------------------------------------")
        CallOverridableSub(sc)
        CallOrdinarySub(sc)
        Console.WriteLine()
        Console.ReadLine()
    End Sub

    ' Calls the OverridableSub method of the instance passed to it
    Public Sub CallOverridableSub(ByVal instance As BaseClass)
        instance.OverridableSub()
    End Sub

    ' Calls the OrdinarySub method of the instance passed to it
    Public Sub CallOrdinarySub(ByVal instance As BaseClass)
        instance.OrdinarySub()
    End Sub
End Module


' BaseClass impliments an overridable and ordinary method
Public Class BaseClass
    Public Overridable Sub OverridableSub()
        Console.WriteLine("   BaseClass.OverridableSub() called")
    End Sub
    Public Sub OrdinarySub()
        Console.WriteLine("   BaseClass.OrdinarySub() called")
    End Sub
End Class

' SubClass impliments an overriden BaseClass with overrides and shadows modifiers
Public Class SubClass
    Inherits BaseClass

    Public Overrides Sub OverridableSub()
        Console.WriteLine("   SubClass.OverridableSub() called")
    End Sub
    Public Shadows Sub OrdinarySub()
        Console.WriteLine("   SubClass.OrdinarySub() called")
    End Sub
End Class

What happens when we execute our code now?

+ Calling BaseClass Methods
--------------------------------------------------
   BaseClass.OverridableSub() called
   BaseClass.OrdinarySub() called

+ Calling SubClass Methods
--------------------------------------------------
   SubClass.OverridableSub() called
   SubClass.OrdinarySub() called

+ Calling SubClass Methods passed as BaseClass
--------------------------------------------------
   SubClass.OverridableSub() called
   BaseClass.OrdinarySub() called

Notice that we are passing the same instance into both methods. Both methods are accepting “BaseClass”, not “SubClass” as a parameter. Our results are completely different. For our OverridableSub, our SubClass method is still called even though we passed this in as a BaseClass instance. However, for our OrdinarySub that used the Shadows modifier, we are getting results from our BaseClass. That is because of some fundamentals in Object Oriented programming. When we override behavior, its overriden no matter how we pass the class to a parameter (with some exceptions made during type casting). However, when we override using the Shadows modifier, our old functionality is only “lurking in the shadows” — not completely overriden. Remember this when trying to override functionality that wasn’t designed to be overriden as such. Your Shadows modifier may help you out when calling against your SubClass, but not when executing against a BaseClass instance.

Fun with default compilation: VB.NET vs C#

I’m not a language elitist by any means. I came from a Visual Basic background and avoided C++ when I could. These days, however, I’m more of a C# guy. I feel like there is sufficient gain in using the language without much, if any development-time penalty associated with using it. While I don’t mind someone stating their reasons for using one language over the other, I will not tolerate the argument that these languages compile to the same IL and work just as well. The VB.NET and C# compilers were written by two different teams. They emitted MSIL completely different from one another by default, and with good reason on both sides. As such, there are some major differences in the IL that is output. I pointed one out the other day when talking about delegate implementation in C# vs VB.NET. Today, I’m noting another.


VB and C# Specific Language


Let’s take a look at the following scenario. I’ve created two projects in both languages and implemented the same code in both. In the form’s class, I have an array list with 100 items in it, a button control and a label control. For the button’s click event handler, I added the following code:

Private Sub Button1_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) _
   Handles Button1.Click

   For i As Int32 = 1 To list.Count
     Me.lblOutput.Text += list(i - 1).ToString()
   Next
End Sub

This code simply loops through all of the items in the array list and outputs them to the label. Notice that I’m not caching the results of list.Count first. Instead, I’m evaluating this each time in the loop. This raises the hairs on the backs of several people’s necks every time I talk about it. I’ll explain my decision to do this later though. In the mean time, let’s look at what the C# output looks like:

for( int i = 1; i <= list.Count ; i++ ) {
    this.lblOutput.Text += list[i-1].ToString();
}

Again, this whole section has the least optimal of coding decisions, but it is done in an attempt to make these two pieces of code do the same work.


The IL Comparison


These look about the same, but the problem is evident when you look at the IL. Yesterday I posted an example where the IL in VB.NET was using virtual dispatch for delegates whereas C# was using instance dispatch. Virtual dispatches are much more expensive. So what is the problem here? Let’s start by looking at the IL for the C# and VB.NET versions of this code. In C# we have a cool 34 lines of IL:

.method private hidebysig instance void button1_Click(object sender,
       class [mscorlib]System.EventArgs e) cil managed
{
  // Code size  64 (0x40)
  .maxstack  5
  .locals init ([0] int32 i)
  IL_0000:  ldc.i4.1
  IL_0001:  stloc.0
  IL_0002:  br.s  IL_0031
  IL_0004:  ldarg.0
  IL_0005:  ldfld class [System.Windows.Forms]System.Windows.Forms.Label CSharpLoop.Form1::lblOutput
  IL_000a:  dup
  IL_000b:  callvirt
            instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()
  IL_0010:  ldarg.0
  IL_0011:  ldfld class [mscorlib]System.Collections.ArrayList CSharpLoop.Form1::list
  IL_0016:  ldloc.0
  IL_0017:  ldc.i4.1
  IL_0018:  sub
  IL_0019:  callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
  IL_001e:  callvirt instance string [mscorlib]System.Object::ToString()
  IL_0023:  call  string [mscorlib]System.String::Concat(string, string)
  IL_0028:  callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)
  IL_002d:  ldloc.0
  IL_002e:  ldc.i4.1
  IL_002f:  add
  IL_0030:  stloc.0
  IL_0031:  ldloc.0
  IL_0032:  ldarg.0
  IL_0033:  ldfld  class [mscorlib]System.Collections.ArrayList CSharpLoop.Form1::list
  IL_0038:  callvirt  instance int32 [mscorlib]System.Collections.ArrayList::get_Count()
  IL_003d:  ble.s  IL_0004
  IL_003f:  ret
} // end of method Form1::button1_Click

But in VB.NET, take a look at the IL hit here — 44 lines of code.

.method private instance void  Button1_Click(object sender,
          class [mscorlib]System.EventArgs e) cil managed
{
  // Code size  72 (0x48)
  .maxstack  5
  .locals init ([0] int32 i,
      [1] class [System.Windows.Forms]System.Windows.Forms.Label _Vb_t_ref_0,
      [2] int32 _Vb_t_i4_0)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  ldarg.0
  IL_0003:  ldfld  class [mscorlib]System.Collections.ArrayList VBLoop.Form1::list
  IL_0008:  callvirt  instance int32 [mscorlib]System.Collections.ArrayList::get_Count()
  IL_000d:  stloc.2
  IL_000e:  stloc.0
  IL_000f:  br.s  IL_0042
  IL_0011:  ldarg.0
  IL_0012:  callvirt instance class [System.Windows.Forms]System.Windows.Forms.Label VBLoop.Form1::get_lblOutput()
  IL_0017:  stloc.1
  IL_0018:  ldloc.1
  IL_0019:  ldloc.1
  IL_001a:  callvirt instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()
  IL_001f:  ldarg.0
  IL_0020:  ldfld  class [mscorlib]System.Collections.ArrayList VBLoop.Form1::list
  IL_0025:  ldloc.0
  IL_0026:  ldc.i4.1
  IL_0027:  sub.ovf
  IL_0028:  callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
  IL_002d:  callvirt  instance string [mscorlib]System.Object::ToString()
  IL_0032:  call  string [mscorlib]System.String::Concat(string,string)
  IL_0037:  callvirt  instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)
  IL_003c:  nop
  IL_003d:  nop
  IL_003e:  ldloc.0
  IL_003f:  ldc.i4.1
  IL_0040:  add.ovf
  IL_0041:  stloc.0
  IL_0042:  ldloc.0
  IL_0043:  ldloc.2
  IL_0044:  ble.s  IL_0011<
  IL_0046:  nop
  IL_0047:  ret
} // end of method Form1::Button1_Click

There are 10 additional IL lines for the same exact code — four of which appear to be unnecessary “nop” fields. The MSDN help for nop states: “Fills space if opcodes are patched. No meaningful operation is performed although a processing cycle can be consumed.” So despite the fact that these instructions do nothing, they can be wasting important processing cycles, which, if executed in a loop such as ours can be quite expensive over the long run.

Let’s break this down a bit further to see exactly what’s happening in these functions. Let’s evaluate the C# side first so I can pick on VB.NET’s IL later and show you where it’s going, well, wrong 🙂


C# IL Code Analysis


First off, the C# header is pretty standard.

.method private hidebysig instance void button1_Click(object sender,
        class [mscorlib]System.EventArgs e) cil managed
{
  // Code size  64 (0x40)
  .maxstack   5

Next we see our locally scoped declarations. In this instance, we only have one variable that is initialized as an int32. This will be the variable that we use in our loop counter.

  .locals init ([0] int32 i)

We then push an int32 value of 1 onto the evaluation stack and immediately pop it back off into the local variable we declared above.

  IL_0000:  ldc.i4.1
  IL_0001:  stloc.0

The next step is fairly interesting for anyone that hasn’t seen IL before. We are transferring control to the instruction at the IL_0031 label. We’ll cover this in a minute.

  IL_0002:  br.s  IL_0031

We are now going to load the first argument onto the evaluation stack (stack size +1). This happens to be the “sender” parameter of the click event. We use the ldfld call to push the label on the stack. The IL is just preparing the text value to be concatenated in the loop.

  IL_0004:  ldarg.0
  IL_0005:  ldfld  class [System.Windows.Forms]System.Windows.Forms.Label CSharpLoop.Form1::lblOutput

Having fun so far? Good, let’s keep on trucking. Next, we are doing something fairly interesting. We are going to duplicate topmost item on the evaluation stack and push it onto the stack as well. The way this happens is fairly complicated for such a small field name. First, the value is pushed onto the stack, popped off the stack and duplicated, then pushed back onto the stack. Once we’ve performed three operations to get that done, we perform one more to push the duplicated value on the stack. Remember out += operator in the code? Sound like something a += operator might want to do? I hope so :). Next, we are going to use callvirt to push the return value of the label’s Text property onto the evaluation stack.

  IL_000a:  dup
  IL_000b:  callvirt  instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()

We’ve seen the next series before so I’ll spare you the detailed explaination. We are pushing our array list onto the stack. We need this so we can get our count later.

  IL_0010:  ldarg.0
  IL_0011:  ldfld  class [mscorlib]System.Collections.ArrayList CSharpLoop.Form1::list

Remember way back at the start of this method, we initialized a local variable? Well now we are going to load it. We then pushes an int32 value of 1 onto the evaluation stack again.

  IL_0016:  ldloc.0
  IL_0017:  ldc.i4.1

We do our subtraction that is done in the array indexer (“i-1”).

  IL_0018:  sub

Next we use callvirt again to get the item at the index provided by the result of the sub field’s return value. Without delay, we call that object’s ToString method and store the return value on the stack.

  IL_0019:  callvirt  instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
  IL_001e:  callvirt  instance string [mscorlib]System.Object::ToString()

Of course, our call is concatenating strings so we call the String.Concat method using our Control’s text value again. Notice when we called concat we are using “call” instead of callvirt? This is because we know the object is a native type, String. We used callvirt against our controls because these objects can be recast at run-time. Therefore the callvirt method is used to call the method against the runtime type of the object, not the compile time type.

  IL_0023:  call  string [mscorlib]System.String::Concat(string,string)
  IL_0028:  callvirt  instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)

Here we go again with this sequence! This time we are loading the values from our first parameter so we can increment the value with the “add” field. This adds the value 1 to the value stored at location 0. Make sense? Good, because we then have to call stloc again to store the value back into location 0.

  IL_002d:  ldloc.0
  IL_002e:  ldc.i4.1
  IL_002f:  add
  IL_0030:  stloc.0

Now we have to load the value stored in our first initialized value again so we can do our “for(;;)” comparison. We compare this value against the value returned from the ArrayList’s Count method.

  IL_0031:  ldloc.0
  IL_0032:  ldarg.0
  IL_0033:  ldfld  class [mscorlib]System.Collections.ArrayList CSharpLoop.Form1::list
  IL_0038:  callvirt  instance int32 [mscorlib]System.Collections.ArrayList::get_Count()

Remember back near the beginning of all of this, we transferred control to an instruction at IL_0031 ? Well now we are transferring control back to IL_0004. If this sounds like loop control instructions to you, you’d be right. Lastly, this method ends with a return call. Since this method is void, we don’t return any values.

  IL_003d:  ble.s  IL_0004
  IL_003f:  ret
  } // end of method Form1::button1_Click

Was this code really necessary for a simple loop!? Sadly, yes. But before you get upset, lets remember that we have 10 extra lines in our VB.NET compiled IL! I wont rehash all of the VB.NET code like we did with C#, but I will concentrate on the differences because that’s what causes our performance hit in VB.NET.


VB.NET IL Code Analysis


Take a look at the first difference — the initialized variables.Notice that we have 3 variables declared here instead of 1. The first is the variable that we use in the loop, and the second is a reference to the label that we will use in the loop. The third is used to cache the value of the Count() method later on. Rather than evaluate this within the loop, we will cache this value in a local variable and use this value in our loop comparison.

 .locals init ([0] int32 i,
      [1] class [System.Windows.Forms]System.Windows.Forms.Label _Vb_t_ref_0,
      [2] int32 _Vb_t_i4_0)

The next thing I’ll touch on is those nasty nop calls. These are annoying but are there for debugging support. These allow you to place break points in code that have no execution. These are just placeholders, but as said, they do waste instructions. Try compiling these in release mode instead of debug mode to get rid of these. You should be doing this anyway when you are testing the performance of your code.

The IL that follows is representative of what we’ve already said. The label will be loaded as a local variable along with a cached value of the variable. These values are obtained and stored in location 0 and 2 respectively. (stloc.0 and stloc.2 fields)

  L_0001: ldc.i4.1
  L_0002: ldarg.0
  L_0003: ldfld [mscorlib]System.Collections.ArrayList VBLoop.Form1::list
  L_0008: callvirt instance int32 [mscorlib]System.Collections.ArrayList::get_Count()
  L_000d: stloc.2
  L_000e: stloc.0

We do the same loop control we had before with the br.s call and then move in to load the first argument (our label) and put it on the stack. We load the value stored in the local variable stored in location 1 twice (ldloc.1). Notice this is different than the C# version of “dup”.

  L_0011: ldarg.0
  L_0012: callvirt instance [System.Windows.Forms]System.Windows.Forms.Label VBLoop.Form1::get_lblOutput()
  L_0017: stloc.1
  L_0018: ldloc.1
  L_0019: ldloc.1

Moving forward we get our text value of the output label and start our loop through the array list.

  L_001a: callvirt instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()
  L_001f: ldarg.0
  L_0020: ldfld [mscorlib]System.Collections.ArrayList VBLoop.Form1::list

We load our first local variable and do our subtraction again. But notice our subtraction call is different.

  L_0025: ldloc.0
  L_0026: ldc.i4.1
  L_0027: sub.ovf

This version of sub.ovf is used to do overflow checking on the subtraction operation. This is turned on by default in VB.NET compilation, but turned off in C# compilation.

We take the same steps to load the item in our array list, get the result of the ToString call, concatenate the value, and then set the text value of our label that we did in the C# version.

  L_0028: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
  L_002d: callvirt instance string object::ToString()
  L_0032: call string string::Concat(string, string)
  L_0037: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)

As we draw near the end of our IL, again go through the steps to increment our loop counter. After we put some more of those annoying little nop calls. Just as the subtraction call did overflow checking, the add method does overflow checking, hence the change from add to add.ovf.

  L_003c: nop
  L_003d: nop
  L_003e: ldloc.0
  L_003f: ldc.i4.1
  L_0040: add.ovf
  L_0041: stloc.0

We end our IL nicely by reloading our variables in position 0 and 2 before returning to the front of our loop.

  L_0042: ldloc.0
  L_0043: ldloc.2
  L_0044: ble.s L_0011
  L_0046: nop
  L_0047: ret
}

Summary


This has really just been an informational look at how the compilers differ by default. Its entirely possible to change a few parameters in the compilers to get the output to look a bit more alike. Its important to know these differences, though, so that you can make educated decisions on how you should optimize your code based on what language you are working with. Happy hacking.

Delegates in C# vs VB.NET down to the IL

So I found a post on a blog the other day from one of my friends. He is a recent convert from VB.NET to C# and he asked where his event handlers were. Anyone that has been coding in both VB.NET and C# knows exactly what the problem is. Many people tend to misunderstand where the .NET runtime ends and language syntax begins. Let’s remember that both languages must compile to Intermediate Language (IL). The way each language chooses to implement .NET’s features in sytax is totally up to the language designer. This post will attempt to show the differences in these languages and break down how this all works behind the scenes. I’ll show you how events are hooked up in VB.NET, then in C#. I’ll show you how these are compiled down to IL and then provide references where you can find more information if you really want it.

First off, lets look at how we implement event handlers for controls. When I double click on a control in a VB.NET Windows Forms project, the development environment drops me into VB.NET code and a newly created event handler. The event handler is hooked up as follows:

Private Sub Button1_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles Button1.Click
End Sub

VB.NET knows that this event (Button1_Click) is handling the Click event of the Button1 object by the very aptly named “Handles” keyword followed by the dotted notation of Object.EventName. This, of course, follows the EventHandler delegate method signature. When I compile this code, the VB.NET compiler outputs the following IL:

IL_0037:  ldarg.0
IL_0038:  dup
IL_0039:  ldvirtftn
          instance void VBHandlers.Form1::Button1_Click(object,
             class [mscorlib]System.EventArgs)
IL_003f:  newobj
          instance void [mscorlib]System.EventHandler::.ctor(object,
             native int)
IL_0044:  callvirt
          instance void [System.Windows.Forms]System.Windows.Forms.Control::add_Click(
             class [mscorlib]System.EventHandler)

This IL is fiarly simple, the ldvirtftn field is pushing the pointer to the Button1_Click function’s implementation onto the stack. This first pushes the Button1 object onto the stack. The object instance is then popped from the stack and the address of the entry point to Button1_Click is retreived. That pointer is then pushed onto the stack. Next the event handler is created with the newobj call, and finally, the callvirt method adds the handler to the Click event. Notice that the click event implements an add_Click syntax. This is because there is a little known feature of .NET events which provide event accessors. Much like you can use Get and Set accessors for properties, you can implement add and remove accessors for events. You might also recognize the prefixed operation on the event is similar to the way that operator overloading looks in IL (i.e. op_Equal).

In C# we have the same convenience of double clicking a control to quickly implement the default event for that control. When we double click the same button in a C# Windows Forms project, we are aslo presented in a C# code window that has the following code:

private void button1_Click(object sender, System.EventArgs e) {
}

You can see that we have our method implemented that matches the delegate method signature, but where is our handler? How does the button know to hook this up? What happens if I rename my button? Does it just know to handle this method when the event is raised based on the method name? Not hardly. The development environment also adds a handler to this method, but it does it in a more object oriented manner. That is, it hooks up the event by an assignment operator. If you look at your C# windows forms code again, look for the “Windows Form Designer generated code” code region and expand it. You’ll notice in the InitializeComponent method, there is a section of this method dedicated to setting the values for the button1 button instance. At the end of this section is code similar to the following:

this.button1.Click += new System.EventHandler(this.button1_Click);

This code tells the event to append an EventHandler to the Click event. That event handler just happens to be our button1_Click method. When we compile our C# code, we get nearly the same IL output:

IL_005a:  ldarg.0
IL_005b:  ldftn
              instance void CSharpHandlers.Form1::button1_Click(object,
             class [mscorlib]System.EventArgs)
IL_0061:  newobj
              instance void [mscorlib]System.EventHandler::.ctor(object,
              native int)
IL_0066:  callvirt
              instance void [System.Windows.Forms]System.Windows.Forms.Control::add_Click(
              class [mscorlib]System.EventHandler)

Did you catch the difference between the C# and VB.NET IL output? We are no longer calling ldvirtftn, but instead, we are simply calling ldftn. This is the difference between VB.NET using a virtual dispatch sequence and C# using an instance dispatch sequence. Both are valid according to Ecma-335 standards. My guess is that if you don’t understand delegates, you won’t get the difference between these two fields. The main thrust of what most need to see is that both languages implement the same functionaility differently through their language syntax. It’s up to the compiler to interpret the syntax and output the appropriate IL code — which more often than not is nearly identical regardless of what language you use. For some languages it may make more sense to use a different IL construct within the same category, but the output is essentially the same. If you attempt to use a different .NET compatible language and you don’t see a feature that you were expecting to see, don’t give up. The feature is most likely implemented in a different way.