Ответ 1
Сначала рассмотрим три варианта, которые вы дали:
If myObject.GetType.Equals(MyClass)
Это, вероятно, приведет к ошибке, поскольку equals ожидает System.Type
, а не класс. Определение класса не является System.Type
, но вы можете получить его, используя оператор typeof
. Таким образом, вы можете сделать instance.Equals(typeof(MyClass))
, который будет возвращать true, если объект принадлежит данному классу.
If TypeOf(myObject) Is MyClass
И наоборот, вы не можете использовать typeof
с экземплярами, только с классами, поэтому приведенный выше код потерпит неудачу. Кроме того, оператор is
автоматически проверяет типизацию, поэтому вы не можете использовать typeof
или GetType
при его использовании. Вы должны пойти дальше, if myObject is MyClass
, который возвращает true, если myObject может быть приведен к MyClass
. Это отличается от того, чтобы сказать, что это экземпляр этого типа, потому что может случиться так, что myObject является экземпляром класса, который наследуется от MyClass
.
If myObject.GetType() Is MyClass
Опять же, оператор is
уже проверяет тип обоих операндов, так что вам следует использовать, if myObject is MyClass
.
При всем этом я хотел бы объяснить "теорию", лежащую в основе системы типов. Я не специалист, поэтому я дам вам более практическое объяснение:
-
Метка определения класса (например,
MyClass
) не является System.Type.System.Type
- это класс метаданных, который генерируется CLR для представления типа, определенного вашей меткой. Чтобы получитьSystem.Type
связанный с определенной меткой определения класса, используйте операторtypeof
следующим образом:System.Type MyClassType = typeof(MyClass);
-
На экземпляре объекта вы можете получить метаданные
System.Type
, вызвав для него методGetType()
. Это даст вам экземплярSystem.Type
связанный с классом, который представляет фактический экземпляр. Это означает, что если ваш объект обрабатывается компилятором как интерфейс или базовый класс,.GetType()
прежнему дает вам наиболее производный тип для этого экземпляра. -
Вы можете сравнить
System.Type
, чтобы проверить, являются ли два объекта экземплярами одного и того же класса, но опять же, имейте в виду, что ваш экземпляр может иметь более производный тип; Равенство не удастся (типSystem.Type
более производного класса отличается от класса менее производного). -
Если вам нужно принять во внимание наследование, вы можете использовать метод
IsAssignableFrom
, например:BaseClass instance = new DerivedClass(); System.Type type = instance.GetType(); if ((typeof(BaseClass)).IsAssignableFrom(type)) // returns true { }
-
С# и VB.Net предоставляют вам два оператора, которые позволяют вам выполнять проверку типов на лету,
is
иas
.is
выполняет автоматическое извлечение ввода и является предпочтительным по сравнению с получениемSystem.Type
самостоятельно. Это также относится к наследованию:DerivedClass instance = new DerivedClass(); System.Type type = instance.GetType(); if (instance is BaseClass) // returns true { }
-
Если вам нужно проверить тип и привести объект, используйте
as
:DerivedClassinstance = new DerivedClass(); System.Type type = instance.GetType(); AnotherClass another = instance as AnotherClass; if (another == null) // returns true { // Do proper error treatment... throw an exception or something }
То, что вы не можете сделать, так
as
не выполняет надлежащую проверку результатов; Проблема в том, что если вы не проверяете его на null и не используете его, вы получаетеNullReferenceException
, которое скроет правильную проблему (приведение не выполнено). Если вы уверены, что можете выполнить приведение, используйте явное приведение:DerivedClassinstance = new DerivedClass(); System.Type type = instance.GetType(); AnotherClass another = (AnotherClass)instance; // throws
Это вызовет
InvalidCastException
, поэтому код будет легче отлаживать.