Что возвращает функция GetType() для экземпляра Type?

#c# #.net-3.5 #types

#c# #.net-3.5 #типы

Вопрос:

Я наткнулся на этот код во время некоторой отладки.

 private bool HasBaseType(Type type, out Type baseType)
{
    Type originalType = type.GetType();
    baseType = GetBaseType(type);
    return baseType != originalType;
}
  

Моя первоначальная мысль заключалась в том, что type.GetType() в первой строке метода всегда будет выдавать эквивалент typeof(System.Type) , что кажется мне действительно бессмысленным в контексте. Однако MSDN предполагает, что Type переопределяет версию, от GetType() которой она будет унаследована Object . Затем фактическая страница MSDN в нестатическом Type.GetType() (не путать с тремя статическими версиями) сообщает, что GetType() метод возвращает «текущий тип». Никаких дополнительных соответствующих объяснений не дается.

Итак, равно ли значение originalType в приведенном выше методе type или typeof(System.Type) ? Я не совсем уверен в документации. Если originalType эквивалентно type , будет ли это копией type , чтобы, если GetBaseType метод изменяет свой параметр, originalType все равно было эквивалентно type в его первоначальной форме, независимо от того, что происходит внутри GetBaseType ?

Комментарии:

1. частный bool имеет BaseType(экземпляр объекта, базовый тип out)

2. Если все, что вам нужно, это базовый тип, почему бы просто не использовать свойство Type.BaseType ?

3. @tkeE2036 Я не писал этот код; Я просто нашел его во время отладки. И, поверьте мне, там (к сожалению) гораздо больше, откуда это взялось.

Ответ №1:

1.

GetType не определен как виртуальный и поэтому не может быть переопределен. Система.Type не переопределяет GetType объекта, он скрывает его (в C # он был бы представлен с помощью ключевого слова new). Если вы используете инструмент для разборки, такой как ILSpy, вы увидите, что он реализован следующим образом:

 public new Type GetType()
{
    return base.GetType();
}
  

Как вы можете видеть, он вызывает только реализацию GetType базового класса (который является object ), поэтому конечный результат тот же. Эта версия GetType предоставляет формальную реализацию интерфейса _Type. Обычно вам не нужно беспокоиться об этом интерфейсе, он существует по соображениям совместимости.

2.

Метод GetType определен в object и возвращает System.Type . Но более пристальный взгляд на Систему.Тип показывает, что он определен как абстрактный, следовательно, он никогда не может быть создан. Таким образом, способ получить что-то конкретное из GetType — это получить другой тип, который является производным от System.Type. И действительно, то, что мы получаем, — это экземпляр System.RuntimeType , который является производным от System.Type.

Причина этого в том, что должен быть только один экземпляр, представляющий данный тип. То есть не имеет значения, сколько разных экземпляров string (например) вы вызываете для GetType , вы все равно получите точно такой же экземпляр, потому что существует только один экземпляр, который описывает строку. Чтобы убедиться, что существует только один экземпляр, System .Тип был определен как абстрактный, поэтому его нельзя создать с помощью пользовательского кода и System.RuntimeType был определен как internal , поэтому он доступен только для кода в mscorlib, а также не может быть создан с помощью пользовательского кода.

3.

Существование System.RuntimeType — это деталь реализации, которая в большинстве случаев может игнорироваться. По сути, ваш код может предполагать, что GetType возвращает экземпляр System.Type . Единственным исключением является следующий код (вы можете заменить string любым другим типом):

 bool b = 
    typeof(string).GetType() == typeof(Type);
  

Если не знать о System.RuntimeType , можно предположить, что b будет true, потому что предполагается, что GetType возвращает System .Тип, который явно является значением выражения справа. Но поскольку левое значение на самом деле System.RuntimeType , b равно false (System.Type и System.RuntimeType — это два разных типа и, следовательно, не равны). Это единственный случай, когда вам нужно знать System.RuntimeType, чтобы понять, почему код ведет себя так, как он есть. В любом другом случае просто не имеет значения, что GetType возвращает System.RuntimeType, и вы можете его игнорировать.

4.

Вот прямая ссылка на ту часть моего онлайн-курса .NET, в которой обсуждается информация о типе среды выполнения (RTTI). Я не упоминаю System.RuntimeType, потому что, как я уже сказал, это деталь реализации, которую по большей части можно игнорировать. Но эта ссылка даст вам больше информации и более четкое представление о System.Type .

http://motti.me/tw

Надеюсь, это поможет!

Мотти

Ответ №2:

Тип экземпляра Type — System.RuntimeType .

     {
        Console.WriteLine(typeof(System.Type).GetType());
        Console.WriteLine(typeof(string).GetType().GetType());
        Console.WriteLine(typeof(int).GetType());
        Console.WriteLine(typeof(List<int>).GetType());
    }

System.RuntimeType 
System.RuntimeType 
System.RuntimeType 
System.RuntimeType
  

Ответ №3:

Похоже, что ни то, ни другое. Когда вы вызываете GetType Type экземпляр, кажется, что он всегда возвращается RuntimeType .

Я проверил это на системной сборке, запустив этот фрагмент кода:

 Assembly
  .GetAssembly(typeof(int))
  .GetTypes()
  .Where(type => type.GetType() == type)
  

Редактировать: как пояснил Люк в комментариях, «исходный тип» на самом деле является исходным типом только при задании a RuntimeType — он не работает ни для чего другого. И поскольку этот тип является внутренним для system, метод кажется просто неправильным.

Комментарии:

1. Итак, если экземпляр System.RuntimeType был передан в метод OP, тогда originalType он действительно был бы равен type . Во всех других случаях они не были бы равны.

2. @LukeH Правильно. Не возражаете, если я отредактирую, чтобы включить это уточнение?