Как проверить, принадлежит ли объект определенному типу

102

Я передаю различные объекты подпрограмме для запуска одного и того же процесса, но каждый раз использую другой объект. Например, в одном случае я использую 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
Лия
источник

Ответы:

160

В 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
Спасибо за Ваш ответ. Я пробовал этот код, но на самом деле единственное, что он не работает с оператором '='. Пришлось поменять его на «Есть». Ошибка, которую я имел, когда было '=', заключалась в том, что «Оператор '=' не определен для типов 'System.Type' и 'System.Type'».
Leah
1
@Leah: Да, извините за это. Похоже, мне стоит уделять больше внимания написанию ответов. TypeOfвозможно, даже более простой вариант, по крайней мере, с точки зрения читабельности кода; Я тоже обновил ответ примером этого.
Коди Грей
35
Между ними есть важное различие, которое и привело меня к этой публикации. Проверка TypeOf вернет True, если объект относится к классу, унаследованному от типа, который вы проверяете, тогда как GetType вернет True, только если это точно такой же класс.
Abacus
Совершенно тривиальный, неуместный контрапункт: несмотря на то, что VS CodeAnalysis жалуется, я все еще чувствую, что имена аргументов являются частью открытого интерфейса, как и PascalCase в моем коде.
Марк Херд
Есть ли разница в производительности между ними? - А как насчет Select Case (Obj.GetType())нескольких тестовых случаев против нескольких IF TypeOf Obj is ...?
Люк Т О'Брайен
3

Еще несколько деталей в связи с ответом Коди Грея. Поскольку мне потребовалось некоторое время, чтобы переварить его, я подумал, что это может быть полезно другим.

Для начала несколько определений:

  1. Есть TypeNames, которые представляют собой строковое представление типа объекта, интерфейса и т. Д. Например, Barэто TypeName in Public Class Barили in Dim Foo as Bar. TypeNames можно рассматривать как «метки», используемые в коде, чтобы сообщить компилятору, какое определение типа искать в словаре, где будут описаны все доступные типы.
  2. Есть System.Typeобъекты, которые содержат значение. Это значение указывает тип; точно так же, как a Stringпринимает текст или Intчисло, за исключением того, что мы сохраняем типы вместо текста или чисел. Typeобъекты содержат определения типа, а также соответствующее ему имя типа.

Во-вторых, теория:

  1. Foo.GetType()возвращает Typeобъект, содержащий тип переменной Foo. Другими словами, он сообщает вам, что Fooявляется экземпляром.
  2. GetType(Bar)возвращает Typeобъект, который содержит тип для TypeName Bar.
  3. В некоторых случаях тип объекта Castотличается от типа, из которого объект был впервые создан. В следующем примере MyObj является преобразованием Integerв Object:

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

Итак, MyObjтипа Objectили типа Integer? MyObj.GetType()скажу вам, что это Integer.

  1. Но вот Type Of Foo Is Barфункция, которая позволяет вам убедиться, что переменная Fooсовместима с TypeName Bar. Type Of MyObj Is Integerи Type Of MyObj Is Objectоба вернут True. В большинстве случаев TypeOf будет указывать, что переменная совместима с TypeName, если переменная относится к этому типу или типу, производному от него. Подробнее здесь: https://docs.microsoft.com/en-us/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)для получения TypeName данного объекта. Например,

Dim Foo as Bar
Dim Result as String
Result = TypeName(Foo)
Debug.Print(Result) 'Will display "Bar"
Ама
источник