Solution
Some research and a better reading of the earlier referred to article mentioned by Hans Passant, brings about the following conclusion:
- VB.NET 2010 supports the DLR;
- You can implement
IDynamicMetaObjectProvider
if you want to explicitly support dynamics, the VB.NET compiler is updated to recognize that;
- VB's
Object
will only use the DLR and method caching if the object implements IDynamicMetaObjectProvider
;
- BCL and Framework types do not implement
IDynamicMetaObjectProvider
, using Object
on such types or your own types will invoke the classical, non-cached VB.NET late-binder.
Background: elaborating on why late-binding caching could help VB code performance
Some people (among whom Hans Passant, see his answer) may wonder why caching or non-caching in late-binding could possibly matter. Actually, it makes a large difference, both in VB and in other late-binding technologies (remember IQueryInterface
with COM?).
Late-binding comes down to a simple principle: given a name and its parameter-declarations, loop through all the methods of this class and its parent classes by means of methods available though the Type
interface (and in VB, a method, a property and a field can look the same, making this process even slower). If you consider that method tables are unordered, then this is easily much more expensive than a single direct (i.e., typed) method call.
If you were capable of looking up the method once, and then storing the method-pointer in a lookup table, this would greatly speed up this process. Cached method binding in the DLR goes one step futher and replaces the method-call with a pointer to the actual method, if possible. After the first call, this becomes an order of magnitude faster for each subsequent call (think 200x to 800x times faster).
As an example of when this matters, here's some code that illustrates this issue. In a case where every class has a .Name
string property, but the classes do not share a common ancestor or interface, you can naively sort lists of any of those types like so:
' in the body of some method '
List<Customers> listCustomers = GetListCustomers()
List<Companies> listCompanies = GetListCompanies()
listCustomers.Sort(MySort.SortByName)
listCompanies.Sort(MySort.SortByName)
' sorting function '
Public Shared Function SortByName(Object obj1, Object obj2) As Integer
' for clarity, check for equality and for nothingness removed '
return String.Compare(obj1.Name, obj2.Name)
End Function
This code (similar at least) actually made it into production with one of my clients and was used in an often-called AJAX callback. Without manually caching the .Name
properties, already on medium sized lists of less than half a million objects, the late-binding code became such a noticeable burden that it eventually brought the whole site down. It proved hard to track down this issue, but that's a story for another time. After fixing this, the site regained 95% of its CPU resouces.
So, the answer to Hans's question "don't you have bigger problems to worry about" is simple: this is a big problem (or can be), esp. to VB programmers who have gotten too careless about using late-binding.
In this particular case, and many like them, VB.NET 2010 has apparently not been upgraded to introduce late-binding, and as such, Object
remains evil for the unaware and should not be compared with dynamic
.
PS: late-binding performance issues are very hard to track down, unless you have a good performance profiler and know how late-binding is implemented internally by the compiler.