如何检查一个对象是否属于特定类型

122

我正在向子程序传递各种对象以运行相同的过程,但每次使用不同的对象。例如,在一个情况下,我正在使用ListView,在另一个情况下,我正在传递DropDownList。

我想检查传递的对象是否为DropDownList,如果是,则执行一些代码。我应该如何做?

到目前为止,我的代码没有起作用:

Sub FillCategories(ByVal Obj As Object)
    Dim cmd As New SqlCommand("sp_Resources_Categories", Conn)
    cmd.CommandType = CommandType.StoredProcedure
    Obj.DataSource = cmd.ExecuteReader
    If Obj Is System.Web.UI.WebControls.DropDownList Then

    End If
    Obj.DataBind()
End Sub
2个回答

204

在VB.NET中,你需要使用GetType方法来获取对象实例的类型,并使用GetType()运算符来获取另一个已知类型的类型。

一旦你获得了这两种类型,你可以简单地使用Is运算符进行比较。

因此,你的代码应该像这样编写:

Sub FillCategories(ByVal Obj As Object)
    Dim cmd As New SqlCommand("sp_Resources_Categories", Conn)
    cmd.CommandType = CommandType.StoredProcedure
    Obj.DataSource = cmd.ExecuteReader
    If Obj.GetType() Is GetType(System.Web.UI.WebControls.DropDownList) Then

    End If
    Obj.DataBind()
End Sub

你也可以使用TypeOf 运算符代替 GetType 方法。请注意,这测试对象是否与给定类型兼容,而不是它们是否为相同类型。该操作将类似于:

If TypeOf Obj Is System.Web.UI.WebControls.DropDownList Then

End If

完全是微不足道、无关紧要的挑剔: 传统上,在编写 .NET 代码(无论是 VB.NET 还是 C#)时,参数名称都采用驼峰命名法(即始终以小写字母开头)。这使得它们很容易在一眼看到时与类、类型、方法等区分开来。


1
谢谢你的回答。我尝试了那段代码,但实际上唯一的问题是它不能与'='运算符一起使用。我不得不将其更改为'Is'。当它是“=”时,我遇到的错误是“类型'System.Type'和类型'System.Type'之间未定义运算符'='”。 - Leah
1
@Leah:是的,对不起。看来我在编写答案时应该更加注意。TypeOf可能是一个更简单的选项,至少在代码可读性方面;我也用一个例子更新了答案。 - Cody Gray
40
两者之间存在重要的区别,这也是我撰写本文的原因。TypeOf检查将返回True,如果对象是从正在进行检查的类型继承的类,而GetType仅在完全相同的类时才返回True。 - Abacus
完全无关紧要的反对意见:尽管VS CodeAnalysis有所抱怨,我仍然认为参数名称是公共接口的一部分,并且在我的代码中应该使用PascalCase。 - Mark Hurd
这两种方法之间有性能差异吗?使用多个测试用例的 Select Case (Obj.GetType()) 和多个 IF TypeOf Obj is ... 有什么区别? - Luke T O'Brien
另一个值得一提的点是:当我们需要通过反射验证MemberInfo对象的确切类型与实际对象的类型时,我们可以使用类似于myMemberInfo.DeclaringType.FullName = myObj.GetType().FullName的方法。这是因为,正如Leah上面提到的那样,我们不能使用'='来比较实际类型。 - Cristian Rusanu

5

以下是与 Cody Gray 的回复相关的更多细节。由于我花了一些时间来理解它,我认为将其翻译出来可能对其他人有用。

首先,一些定义:

  1. 有 TypeNames,它们是对象、接口等类型的字符串表示形式。例如,在 Public Class BarDim Foo as Bar 中,Bar 是 TypeName。TypeNames 可以被视为代码中使用的“标签”,告诉编译器在一个字典中查找所有可用类型的类型定义。
  2. System.Type 对象,其中包含一个值。该值指示一种类型;就像一个 String 接受一些文本或一个 Int 接受一个数字一样,只不过我们存储的是类型而不是文本或数字。Type 对象包含类型定义及其对应的 TypeName。

其次,理论方面:

  1. Foo.GetType() 返回一个 Type 对象,该对象包含变量 Foo 的类型。换句话说,它告诉您 Foo 是哪个实例。
  2. GetType(Bar) 返回一个 Type 对象,该对象包含 TypeName Bar 的类型。
  3. 在某些情况下,对象所转换到的类型与对象最初实例化的类型不同。在以下示例中,MyObj 是被强制转换为 ObjectInteger

    Dim MyVal As Integer = 42 Dim MyObj As Object = CType(MyVal, Object)

那么,MyObj 的类型是 Object 还是 IntegerMyObj.GetType() 将告诉您它是一个 Integer

  1. 但是,在这里出现了 Type Of Foo Is Bar 功能,它允许您确定变量 Foo 是否与 TypeName Bar 兼容。 Type Of MyObj Is IntegerType Of MyObj Is Object 都将返回 True。对于大多数情况,如果变量是该类型或从该类型派生的类型,则 TypeOf 将指示变量与 TypeName 兼容。 更多信息请参见:https://learn.microsoft.com/zh-cn/dotnet/visual-basic/language-reference/operators/typeof-operator#remarks
下面的测试很好地说明了每个提到的关键字和属性的行为和用法。
Public Sub TestMethod1()

    Dim MyValInt As Integer = 42
    Dim MyValDble As Double = CType(MyValInt, Double)
    Dim MyObj As Object = CType(MyValDble, Object)

    Debug.Print(MyValInt.GetType.ToString) 'Returns System.Int32
    Debug.Print(MyValDble.GetType.ToString) 'Returns System.Double
    Debug.Print(MyObj.GetType.ToString) 'Returns System.Double

    Debug.Print(MyValInt.GetType.GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(MyValDble.GetType.GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(MyObj.GetType.GetType.ToString) 'Returns System.RuntimeType

    Debug.Print(GetType(Integer).GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(GetType(Double).GetType.ToString) 'Returns System.RuntimeType
    Debug.Print(GetType(Object).GetType.ToString) 'Returns System.RuntimeType

    Debug.Print(MyValInt.GetType = GetType(Integer)) '# Returns True
    Debug.Print(MyValInt.GetType = GetType(Double)) 'Returns False
    Debug.Print(MyValInt.GetType = GetType(Object)) 'Returns False

    Debug.Print(MyValDble.GetType = GetType(Integer)) 'Returns False
    Debug.Print(MyValDble.GetType = GetType(Double)) '# Returns True
    Debug.Print(MyValDble.GetType = GetType(Object)) 'Returns False

    Debug.Print(MyObj.GetType = GetType(Integer)) 'Returns False
    Debug.Print(MyObj.GetType = GetType(Double)) '# Returns True
    Debug.Print(MyObj.GetType = GetType(Object)) 'Returns False

    Debug.Print(TypeOf MyObj Is Integer) 'Returns False
    Debug.Print(TypeOf MyObj Is Double) '# Returns True
    Debug.Print(TypeOf MyObj Is Object) '# Returns True


End Sub

编辑

您也可以使用Information.TypeName(Object)来获取给定对象的类型名。例如,

Dim Foo as Bar
Dim Result as String
Result = TypeName(Foo)
Debug.Print(Result) 'Will display "Bar"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接