locked
Compiler difference and IL interpretation between C# and VB.NET RRS feed

  • Question

  • I've stumbled upon an issue on which I can't get my head around ...

    The code below compiles and works perfectly with VB.NET at the end of the line.
    But with C# the code does not get compiled....

    In short we've got a base class, written in C#, with two virutal methods (same name, different sig)
    Next we have a derrived class which overrides one of those methods.
    The derrived class has been implemented both in C# as in VB.Net.

    And the end of the line we have small console application that simply calls the methods on both derrived classes.
    There are also two version of the console application, one in C# and one in VB.Net.

    The VB.Net applications compiles and works perfectly.
    The C# version does not even compile.

    We've already found a solution : change the derrived class in VB.Net and add the overloads keyword (in addition to override) and then the C# version also works.

    What I don't understand is why the VB.Net application worked in the first place and the C# did not...
    And secondly, why does the overloads keyword need to be added to solve the issue? (we are overriding, not hiding)
    Is that the right solution?

     

    The base class (c#)

    namespace WeirdStuff
    {
     public abstract class BaseClass 
     {
      public virtual string getMethodSig(int i)
      {
       return "string BaseClass.getMethodSig(int i)";
      }
      public virtual string getMethodSig(string s)
      {
       return "string BaseClass.getMethodSig(string s)";
      }
     }
    }
    
    
    The derrived class, c# version

    namespace WeirdStuff
    {
     public class CSharpDerrivedClass : WeirdStuff.BaseClass
     {
    
      public override string getMethodSig(string i)
      {
       return "string CSharpDerrivedClass.getMethodSig(string i)";
      }
     }
    }
    

    The derrived class, VB.Net version

    Public NotInheritable Class VBDerrivedClass
     Inherits WeirdStuff.BaseClass
    
     Public Overrides Function getMethodSig(ByVal s As String) As String
      Return "string VBDerrivedClass.getMethodSig(string s)"
     End Function
    
    End Class

    The console application, C# version (does not compile)

    namespace CSharpClient
    {
     class Program
     {
      static void Main(string[] args)
      {
    
       WeirdStuff.CSharpDerrivedClass _csharp = new WeirdStuff.CSharpDerrivedClass();
       System.Diagnostics.Debug.WriteLine(_csharp.getMethodSig((int)1));
       System.Diagnostics.Debug.WriteLine(_csharp.getMethodSig("test"));
    
       WeirdStuff.VBDerrivedClass _vb = new WeirdStuff.VBDerrivedClass();
       System.Diagnostics.Debug.WriteLine(_vb.getMethodSig((int)1));
       System.Diagnostics.Debug.WriteLine(_vb.getMethodSig("test"));
      
      }
     }
    }
    

    The console application, VB.Net (works like a charm)

    Module Module1
    
     Sub Main()
    
      Dim _csharp As WeirdStuff.CSharpDerrivedClass = New WeirdStuff.CSharpDerrivedClass()
      System.Diagnostics.Debug.WriteLine(_csharp.getMethodSig(1))
      System.Diagnostics.Debug.WriteLine(_csharp.getMethodSig("test"))
    
    
      Dim _vb As WeirdStuff.VBDerrivedClass = New WeirdStuff.VBDerrivedClass()
      System.Diagnostics.Debug.WriteLine(_vb.getMethodSig(1))
      System.Diagnostics.Debug.WriteLine(_vb.getMethodSig("test"))
    
     End Sub
    
    End Module
    

     

    Thursday, September 2, 2010 11:16 AM

Answers

  • It's been a while since I last looked at this. But IIRC, the CLR supports at least two ways of how derived members can hide members in a base class. They can either hide by name, or hide by name and signature. The latter hides only the base method with the same signature.

    In C# you always get the hide by name and signature behaviour. In VB you have a choice; Overrides hides by name and Overrides Overloads hides by name and signature. You can see the difference if you open the assemblies in Ildasm and look for the hidebysig modifier.

    Combine this with slightly different rules for how the languages decide which members are available (C# will not look at base class methods if there are eligible methods in a derived class), and you get the behaviour you're seeing.

    If you want more details, consult the respective language specification and possibly the ECMA CLI spec.


    Mattias, C# MVP
    • Marked as answer by Wim De Ceuster Friday, September 3, 2010 5:20 AM
    Thursday, September 2, 2010 1:12 PM

All replies

  • It's been a while since I last looked at this. But IIRC, the CLR supports at least two ways of how derived members can hide members in a base class. They can either hide by name, or hide by name and signature. The latter hides only the base method with the same signature.

    In C# you always get the hide by name and signature behaviour. In VB you have a choice; Overrides hides by name and Overrides Overloads hides by name and signature. You can see the difference if you open the assemblies in Ildasm and look for the hidebysig modifier.

    Combine this with slightly different rules for how the languages decide which members are available (C# will not look at base class methods if there are eligible methods in a derived class), and you get the behaviour you're seeing.

    If you want more details, consult the respective language specification and possibly the ECMA CLI spec.


    Mattias, C# MVP
    • Marked as answer by Wim De Ceuster Friday, September 3, 2010 5:20 AM
    Thursday, September 2, 2010 1:12 PM
  • If Overrides in VB.Net realy means hides by name, then the VB.NET compiler should act accordingly.

    In other words, in this example the methods of the base class should have been hidden and the VB.NET client application should not have been able to compile.

    Friday, September 3, 2010 5:19 AM