Solution
一些研究和更好的阅读之前提到的文章 http://msdn.microsoft.com/en-us/magazine/ee336123.aspx汉斯·帕桑特(Hans Passant)提到,得出以下结论:
- VB.NET 2010支持DLR;
- 你可以实施
IDynamicMetaObjectProvider
如果您想显式支持动态,则更新 VB.NET 编译器以识别这一点;
- VB's
Object
仅当对象实现时才使用 DLR 和方法缓存IDynamicMetaObjectProvider
;
- BCL 和 Framework 类型未实现
IDynamicMetaObjectProvider
, using Object
在此类类型或您自己的类型上将调用经典的、非缓存的 VB.NET 后期绑定器。
背景:详细阐述为什么后期绑定缓存可以提高 VB 代码性能
有些人(其中包括 Hans Passant,请参阅他的答案)可能想知道为什么后期绑定中的缓存或非缓存可能很重要。实际上,无论是在 VB 中还是在其他后期绑定技术中,它都有很大的不同(记住IQueryInterface
与 COM?)。
后期绑定归结为一个简单的原则:给定名称及其参数声明,通过可用的方法循环遍历此类及其父类的所有方法Type
接口(在 VB 中,方法、属性和字段可以look同样的,使这个过程更慢)。如果您认为方法表是无序的,那么这很容易比单个直接(即类型化)方法调用昂贵得多。
如果您能够查找该方法一次,然后将方法指针存储在查找表中,这将大大加快此过程。 DLR 中的缓存方法绑定更进一步,如果可能的话,用指向实际方法的指针替换方法调用。第一次调用后,后续每次调用的速度都会快一个数量级(想想快 200 倍到 800 倍)。
作为何时重要的示例,下面是一些说明此问题的代码。如果每个班级都有一个.Name
string 属性,但这些类不共享共同的祖先或接口,您可以天真地对任何这些类型的列表进行排序,如下所示:
' 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
这段代码(至少类似)实际上已与我的一个客户一起投入生产,并在通常称为 AJAX 回调的过程中使用。无需手动缓存.Name
属性,已经在不到 50 万个对象的中等规模列表中,后期绑定代码成为如此明显的负担,最终导致整个站点瘫痪。事实证明很难找到这个问题,但这是另一个故事了。修复此问题后,该站点恢复了 95% 的 CPU 资源。
那么,汉斯问题的答案“你没有更大的问题要担心吗”很简单:这是一个大问题(或者可能是),尤其是。对于对使用后期绑定过于粗心的 VB 程序员来说。
在这种特殊情况下,以及许多类似的情况,VB.NET 2010 显然没有升级以引入后期绑定,因此,Object
对于不知情的人来说仍然是邪恶的,不应该与dynamic
.
PS:后期绑定性能问题很难追踪,除非您有良好的性能分析器并且知道编译器内部如何实现后期绑定。