Friday, July 25, 2008

MyClass in VB.Net

It's always a bit of a shock when you find something you've missed in a language you've used for years. I'm mostly a C# person, but I thought I knew pretty much all of VB.Net's quirks by now. But I totally missed 'MyClass'.

'MyClass' allows a class to access methods and properties as declared on itself, irrespective of them being overridden further down the inheritance heirachy. It's like using 'Me' if all the 'overridable's were removed.

Since there's no C# equivilent this was a big surprise to me, but it shouldn't have been - it's only doing the same as 'MyBase' does (against a type's ancestor): executing properties / methods by specific type address, not via virtual dispatch. As the IL for this sample shows:


Public Class Class1
Public Overridable ReadOnly Property Name()
Get
Return "Class1"
End Get
End Property
End Class

Public Class Class2
Inherits Class1
Public Overrides ReadOnly Property Name()
Get
Return "Class2"
End Get
End Property

Public Function GetNames() As String
Dim lines(3) As String
lines(0) = MyBase.Name
lines(1) = MyClass.Name
lines(2) = Me.Name
Return String.Join(",", lines)
End Function
End Class

Public Class Class3
Inherits Class2
Public Overrides ReadOnly Property Name()
Get
Return "Class3"
End Get
End Property
End Class
Calling new Class3().GetNames() produces the following (edited for brevity)


     // mybase - explicit dispatch to class1
L_000b: call instance object ConsoleApplication1.Class1::get_Name()

// myclass - explicit dispatch to class2
L_001a: call instance object ConsoleApplication1.Class2::get_Name()

// me - virtual dispatch, will resove to class3's implementation
L_0029: callvirt instance object ConsoleApplication1.Class2::get_Name()
So the output eventually is 'Class1, Class2, Class3'. Nifty. That being said, I can't honestly say I've ever really needed this, so it might go back into the 'curios' collection. Useful in a pinch maybe, but surely it's a smell? As if designing-for-subclassing wasn't hard enough as it is...


PS: Interestingly the Reflector disassembler doesn't understand this either, so it wasn't just me that missed it: Reflector thinks the VB was:

Public Function GetNames() As String
Dim lines As String() = New String(4 - 1) {}
lines(0) = Conversions.ToString(MyBase.Name)
lines(1) = Conversions.ToString(Me.Name) ' got this wrong
lines(2) = Conversions.ToString(Me.Name)
Return String.Join(",", lines)
End Function

No comments:

Popular Posts