2013-07-05 3 views
20

Кто-нибудь знает какие-либо различия между typeof(T) where T : struct, , например, t.GetType() where t is a System.Object?
ILdasm показывает, что typeof (T) использует System.Type::GetTypeFromHandle(RuntimeTypeHandle handle), а другой - просто System.Object::GetType(). Реализации являются [MethodImpl(MethodImplOptions.InternalCall)], , поэтому методы определены в собственном коде в среде CLR. Итак, мне просто интересно, знает ли кто-нибудь о какой-либо причине, предпочитающей друг друга?typeof (T) vs. Object.GetType() performance

EDIT: Позвольте мне пояснить, меня интересуют в основном случаи, когда кажется, что вы не выбрали - то есть, есть разница в производительности или по любой другой причине? Благодаря!

+2

Если вы знаете статически (во время компиляции) какой тип вы хотите, используйте typeof. В противном случае используйте GetType(), чтобы получить его во время выполнения. –

+0

Я понял, что perf of typeof (T) будет лучше Object.GetType(), но на самом деле он, вероятно, совершенно незначителен. –

+0

Возможный дубликат [Тип Проверка: typeof, GetType или есть?] (Http://stackoverflow.com/questions/983030/type-checking-typeof-gettype-or-is) – Amicable

ответ

41

typeof используется, если вы хотите получить экземпляр Type, представляющий определенный тип. GetType дает тип времени выполнения объекта, на который он вызывается, который может отличаться от объявленного типа.

Например:

class A {} 

class B : A {} 

class Program 
{ 
    static A CreateA() 
    { 
     return new B(); 
    } 

    static void Main() 
    { 
     A a = CreateA(); 
     Console.WriteLine(typeof(A));  // Writes "A" 
     Console.WriteLine(a.GetType()); // Writes "B" 
    } 
} 

В приведенном выше случае, в рамках метода Main, вы имеете дело с экземплярами типа A; таким образом, если вы заботитесь о объявленном типе, вы должны использовать typeof(A). Однако метод CreateA фактически возвращает экземпляр производного класса, B, несмотря на объявление базового класса в качестве возвращаемого типа. Если вы хотите узнать об этом типе времени выполнения, вызовите GetType на возвращаемом экземпляре.

Редактировать: Замечания Мехрдада в правильном направлении. Хотя typeof испускает вызов GetTypeFromHandle, который принимает параметр RuntimeTypeHandle в качестве параметра, указанный параметр будет фактически соответствовать конкретному типу, токен метаданных которого находится в стеке оценки. В некоторых случаях этот токен будет неявно (из-за текущего вызова метода); в противном случае он может быть явно нажат, вызвав ldtoken. Вы можете увидеть больше примеров этого в этих ответах:

Редактировать: Если вы ищете тесты производительности, вы можете обратиться к Jon Skeet's answer. Его результаты были:

typeof(Test): 2756ms 
test.GetType(): 3734ms 
+0

Вот что я бы подумал, но тогда, если вы посмотрите на IL, typeof (T) генерирует класс [mscorlib] System.Type [mscorlib] System.Type :: GetTypeFromHandle (valuetype [mscorlib] System.RuntimeTypeHandle) ... что, кажется, кажется, что вы получаете тип времени выполнения, нет? –

+0

@RichardHein: Я думаю, вы можете ввести в заблуждение «RuntimeTypeHandle» с типом «run-time type» (a.k.a. «dynamic type») объекта. – Mehrdad

+0

@Mehrdad Да, наверное. ;) –

4

Ну, иногда в родовом коде, вы знаете тип времени компиляции от параметра типа T, не имея экземпляр. Затем вы должны использовать typeof(T).

В других случаях, обычно в не общем коде, вам может быть интересен тип времени выполнения объекта. Затем вы используете GetType().

Так что в некоторых случаях, в зависимости от того, что вы хотите знать, или чего вы можете запросить, у вас есть только один вариант.

И иногда вы можете выбрать.

2

GetType() используются для получения типа экземпляра, который на самом деле у вас есть, но typeof() используется для получения экземпляра типа, что вы не имеете также GetType() получает разрешена во время выполнения, в то время как typeof() разрешен во время компиляции.

+2

'typeof()' is ** not ** разрешено во время компиляции, это приводит к вызову метода. – MarioDS

+0

@MDeSchaepmeester прав: typeof() разрешен для вызова метода. 'Type.GetTypeFromHandle (RuntimeTypeHandle дескриптор)'. -1 –

3

Вы используете typeof, когда хотите получать информацию о компиляции и GetType, когда хотите получить информацию о времени исполнения.

Если вы находитесь в ситуации, когда вы можете использовать либо, вы должны использовать typeof, потому что его можно решить во время компиляции. Это дает более четкое представление о значении типа и (в принципе) позволяет увеличить оптимизацию.

TypeOf ключевое слово имеет идентификатор типа во время компиляции и дает соответствующее время выполнения экземпляра Тип:

Type intType = typeof(int); 
Type stringType = typeof(string); 
Type objectType = typeof(object); 
Type genericType = typeof(T); 

// not permitted: typeof(1), typeof(someVariable) 

Метод экземпляра GetType принимает экземпляр во время выполнения и говорит вам его точный тип выполнения:

Type intType = 1.GetType(); // typeof(int) 
Type objectType = new Object().GetType(); // typeof(object) 

object x = "test"; 
Type stringType = x.GetType(); // typeof(string), NOT typeof(object) 

// not permitted: int.GetType(), string.GetType(), T.getType() 

Вы, как правило, необходимо использовать только TYPEOF или GetType когда-то писал, что делает отражение, создавая деревьев выражений вручную, или используя ужасные методы Enum (которые принимают экземпляр типа вместо универсального параметра типа).