Extension methods and late binding (Extension Methods Part 4)

Published 24 January 07 02:09 PM

This is the fourth installment in my series of posts about extension methods. You can find links to the rest of the series here.

Today I'm going to talk about extension methods and late binding. Essentially there isn't much to say about it, other than the fact that we don't support late bound execution of extension methods. For the most part this isn't a big deal as one of the primary benefits of extension methods is its interaction with intellisence which doesn't work in late bound scenarios anyways. Unfortunately, however, there is one big side effect of this decision that you need to be aware of when authoring extension methods. Mainly, we do not allow extension methods to be called off of any expression that is statically typed as "Object". This was necessary to prevent any existing late bound code you may have written from being broken by extension methods. Too see why, consider the following example:

Class C1 
   
Public Sub Method1()
       
Console.WriteLine("Running c1.Method1")
   
End Sub
End Class

Class C2
   
Public Sub Method1()
       
Console.WriteLine("Running c2.Method1")
   
End Sub
End Class

Module M1
   
Public Sub Main()
       
Dim x As Object = Nothing 
        
If (SomeCondition()) Then
           
x = New C1
       
Else
           
x = New C2
       
End If
       
x.Method1() 
    End Sub
End
Module

Here we have a program which uses late binding in order to invoke the method "Method1" on an object that is either of type "c1" or of type "c2". It does this because the static type of the variable "x" is declared as object, which causes the compiler to resolve any calls to "unknown" methods as late bound calls that will be resolved at runtime based on the dynamic type of the object stored in "x". Extension methods, however, are always fully resolved at compile time. As a result, if we were to add an extension method defined on Object, like so:

<Extension()> _
Public Sub Method1(ByVal x As Object)
   
Console.WriteLine("Running Extension method m1.Method1")
End Sub

Then the act of simply importing the namespace containing the method would cause the formerly late bound method call to Method1 to be transformed into an early bound call to the extension method. This would not be good, as it would silently change the meaning of the program, which would have the potential of making extension methods very, very dangerous. In fact, we explicitly disallow this in early bound scenarios by always having instance methods defined on a type shadow any extension methods defined on it with the same name. This enables you to import extension methods into your existing code without having to worry about things blowing up in your face.

In the case of late bound calls, however, we can't use the same shadowing semantics that we do with early bound method calls because we don't know the actual type of the object we will be calling the method on, so we don't have a list of methods we can check against at compile time. As a result, the only way we could prevent extension methods from completely breaking existing late bound code was to prevent them from being used on anything typed as object.

This has the effect of slightly changing the meaning of an extension method defined on object. Consider the following non-object extension method:

<Extension()> _
Public Sub Method2(ByVal x As System.Windows.Forms.Control)
End Sub

Here the declaration of "Method2" implies that the method is an extension method applicable to the type System.Windows.Froms.Control and any class that derives from it, such as TextBox or DataGridView. In the case of "Method1", however, the method declaration implies that it is applicable to "all types except object". This is a little unfortunate, as it is an inconsistency in the language, but we felt it was much better in this case to be safe than it was to be consistent.

That's all I have for today. In my next post I'll talk about extension methods and generics.

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# The Visual Basic Team : Articles about Extension Methods said on January 24, 2007 5:17 PM:

PingBack from http://blogs.msdn.com/vbteam/pages/articles-about-extension-methods.aspx

# Anthony D. Green, MCPD said on January 24, 2007 10:42 PM:

What about extensions on unconstrained generic type parameters?

I recall Paul Vick's post about resolving extensions on late bound objects and as fantastical as it seemed at the time I can appreciate your decision to drop it. And given the limited interface of Object it would be much effort for little practical benefit to end users.

I suppose the only other compromise would be to disallow  extentions on type object with Option Strict Off which is inconsistent and once again kinda useless.

I know I've been kinda emotional lately about the VB9 dream dying (scope reduction) a little in the last few but  I think this was a really good call on the part of the VB Team, and wanted to applaud your good judgment, for what my not-always-so-humble opinion's worth.

-Anthony

# VBTeam said on January 24, 2007 10:58 PM:

Anthony,

Thanks for the feedback. We like to get both good feedback and bad feedback about what we are doing, so don't ever feel bad about sharing your opion with us. We wouldn't be able to build great products without it.

Also, the unconstrained type parameter case will behave identically to the object case.

-Scott Wisniewski

# Anthony D. Green, MCPD said on January 28, 2007 3:12 PM:

Can someone update the VB9 language overview to reflect all the design and scope decisions since it was last written. I would appreciate an up-to-date and accurate picture of what I'm begging my employer to adopt.

# Mike McIntyre MVP said on January 29, 2007 11:27 AM:

I second Anthony's request for an update to the VB9 document. Not to be negative but its long overdue.

# The Visual Basic Team said on March 10, 2007 6:40 PM:

This is the sixth installment in my series of posts about extension methods. You can find links to the

Leave a Comment

(required) 
(optional)
(required) 

This Blog

Syndication

Page view tracker