Перевірте, чи є екземпляр типу


181

Використовуючи це, щоб перевірити, чи cє примірник TForm.

c.GetType().Name.CompareTo("TForm") == 0

Чи є більш безпечний спосіб зробити це, окрім використання stringв якості параметрі CompareTo()?


20
Я, звичайно, сподіваюся, що ви також не зробите цього на Java. Java instanceofта C # ' isє набагато кращі способи зробити це.
Powerlord

Відповіді:


410

Тут різні відповіді мають два різних значення.

Якщо ви хочете , щоб перевірити , є чи екземпляр має точного типу , то

if (c.GetType() == typeof(TForm))

це шлях.

Якщо ви хочете знати, чи cце екземпляр TForm або підклас, тоді використовуйте is/ as:

if (c is TForm)

або

TForm form = c as TForm;
if (form != null)

Варто чітко зрозуміти, яку саме з таких поведінок ви бажаєте.


7
Невелика примітка: використовуйте "є", якщо ви не хочете використовувати результат амплуа і використовувати "як", якщо це зробити.
Aviram Fireberger

14
З C # 7 ви можете поєднувати isта asзіставляти візерунок:if (x is TForm tf) {…
Річард

39
if(c is TFrom)
{
   // Do Stuff
}

або якщо ви плануєте використовувати cяк TForm, використовуйте наступний приклад:

var tForm = c as TForm;
if(tForm != null)
{
   // c is of type TForm
}

Другий приклад потрібно лише перевірити, чи cє він типу TFormодного разу. Якщо ви перевіряєте, чи бачите, чи cє тип, TFormа потім видаєте його, CLR проходить додаткову перевірку. Ось довідка .

Редагувати: Вкрадено у Джона Скіта

Якщо ви хочете, щоб переконатися, що cце, TFormа не будь-який клас, успадкований від TForm, тоді використовуйте

if(c.GetType() == typeof(TForm))
{
   // Do stuff cause c is of type TForm and nothing else
}


10

Також дещо в тому ж ключі

Type.IsAssignableFrom(Type c)

"Вірно, якщо c і поточний Type являють собою один і той же тип, або якщо поточний Type знаходиться в ієрархії спадкування c, або якщо поточний Type - це інтерфейс, який реалізує c, або якщо c - параметр загального типу та поточний тип являє собою одне з обмежень c ".

Звідси: http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx


це теж мій особистий фаворит. typeof(Class).IsAssignableFrom(object.getType())схожий на instanceofоператора Java .
SkidRunner

Чи дає це помилкове значення, якщо вони не в одній гілці ієрархії спадкування, але існує оператор перетворення?
Пол Стеліан

Хороше запитання @PaulStelian. Я не впевнений, що в голові, але я гадаю, що це поверне помилкове в цій ситуації. Принаймні, це моє очікуване поведінку. Можливо, якщо існує неявна конверсія, вона може повернути істину, але це було б дивним.
Бред Каннінгем

Кожен, у кого встановлена ​​Visual Studio, щоб спробувати це?
Пол Стеліан

1
@PaulStelian - він повертає помилку. Це можна побачити, перейшовши за посиланням на doc, і спостерігаючи, що про конверсії немає жодної згадки. Ще один спосіб подумати над цим - це T1.IsAssignableFrom(T2)повернення trueв ситуаціях, коли asоператор повертає ненулеве значення, враховуючи екземпляри цих типів.
ToolmakerSteve

9

Трохи більш компактний, ніж інші відповіді, якщо ви хочете використовувати c як TForm:

if(c is TForm form){
    form.DoStuff();
}


2

Як уже згадували інші, ключове слово "є". Однак якщо ви збираєтесь пізніше передати це типу, наприклад,

TForm t = (TForm)c;

Тоді слід використовувати ключове слово "як".

напр TForm t = c as TForm.

Потім ви можете перевірити

if(t != null)
{
 // put TForm specific stuff here
}

Не поєднуйте так, як це, тому що це дублікат чека.



-1
bool isValid = c.GetType() == typeof(TForm) ? true : false;

або простіше

bool isValid = c.GetType() == typeof(TForm);

ІМХО: Я б уникнув прямого співчуття (тобто ==). На об'єктних або орієнтованих мовах, що підтримують успадкування, якщо ви не знаєте, що ваш конкретний тип ніколи не буде успадкований, наприклад, від sealedкласу. Також: мене турбує використання потрійного оператора, що повертає (статичні / постійні) булеві значення, я б менше турбував, якби це було switchтвердженням.
SkidRunner
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.