一篇旧文章,保存留档。
如何在运行时分析一个对象的类型呢?你也许会立刻想到 GetType 方法。没错!这个方法可以很方便地获取到一个对象的运行时类型(Type),但如何与类型模板(Class)进行比较呢?
直接利用 Type = Class 或者 Type Is Class 是不可以的,我们必须要首先获得这个类型模板的运行时类型,可以利用GetType关键字来获取。注意:GetType 在VB中是一个关键字,它的使用方法如:Dim t As Type = GetType(Integer)
假设已有一个Object对象sender,我们来分析它是否是一个Button类型。
方法1:
If sender.GetType Is GetType(Button) Then
MsgBox("对象是Button类型!")
End If
方法2:
If sender.GetType.Equals(GetType(Button)) Then
MsgBox("对象是Button类型!")
End If
方法3:
If GetType(Button).Equals(sender.GetType) Then
MsgBox("对象是Button类型!")
End If
上面的方法都能很好的工作,但是这个比较过程都比较复杂。
方法1实现获取对象的运行时类型,然后获取类型模板的运行时类型,最后再对两个运行时类型进行比较。
方法2和方法3雷同,都是获取两个运行时类型,然后再对另一个类型进行基础比较。
方法2的IL代码如下:
IL_0001: ldarg.1
IL_0002: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0007: ldtoken [System.Windows.Forms]System.Windows.Forms.Button
IL_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0011: callvirt instance bool [mscorlib]System.Type::Equals(class [mscorlib]System.Type)
IL_0016: stloc.0
首先从参数中加载参数sender,然后调用其GetType方法,接着使用ldtoken命令将Class转换为Type(实际上是RuntimeTypeHandle对象),最后执行比较。基本上,上面方法的代码在运行过程中的效率并不高。
我们再来看最后一个解决方法:
If TypeOf sender Is Button Then
MsgBox("对象是Button类型!")
End
先来认识一下 TypeOf 关键字,它在C#中如同VB中GetType关键字一样,是获取模板类型的运行时类型的关键字,但在VB中却拥有完全不同的功能,就是检测对象类型的功能!TypeOf 返回的是一个Boolean 类型的值,用以检测一个对象是否是目标类型,它在执行过程中完全不进行类型转换,我们来看看它生成的IL代码:
IL_0001: ldarg.1
IL_0002: isinst [System.Windows.Forms]System.Windows.Forms.Button
IL_0007: ldnull
IL_0008: cgt.un
IL_000a: stloc.0
实际上上面的IL代码甚至可以直接省略为:
ldarg.1
isinst [System.Windows.Forms]System.Windows.Forms.Button]
stloc.0
由此可见,TypeOf 对应的是 isinst 命令,它的效率明显要比上面的 GetType 要高。
因此,在进行类型比较分析时,使用 TypeOf 要比 GetType 要更好。