Typeof(T) против нового T().GetType()

Гарантируется ли совпадение двух выражений?

В универсальном методе Foo<T> where T : new() ... всегда ли это выражение true?

typeof(T) == new T().GetType()

Я не понимаю, как это может быть ложным, но, возможно, я упускаю крайний случай.

Я не думаю, что это рассматривается в любом из следующих связанных вопросов:

Этот код создает объекты конкретного объекта System.RuntimeType. Цитата: все классы, начинающиеся со слова Runtime, создаются только один раз для каждого объекта в системе и поддерживают операции сравнения

Hans Passant 29.05.2023 15:27

Немного тангенциально, но typeof(T) не заботятся о параметрах конструктора T are. new T().GetType() делает: для этого требуется конструктор без параметров.

ProgrammingLlama 29.05.2023 15:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
73
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я полагаю, что они всегда дают один и тот же результат. Разница в том, что для typeof вам не нужно создавать новый экземпляр T, что скорее хорошо. Также семантически более очевидно, если вы используете typeof для проверки типа, а не для создания экземпляра объекта.

Ответ принят как подходящий

typeof(T) и new T().GetType() не совсем идентичны. На самом деле new T().GetType() не «безопасен».

Учтите, что когда T является int? или чем-то подобным, тогда new T() приведет к null — фактически экземпляру int? с HasValue = false, который на самом деле является структурой. Упаковывание типа значения, допускающего значение NULL, который не имеет значения, приводит к null, а вызов метода, унаследованного от object, сначала упаковывает значение. Таким образом, в этом случае new T().GetType() выдает исключение нулевой ссылки.

всегда ли верно это выражение
typeof(T) == new T().GetType()

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

Я думаю, что конструктор для T тоже может генерировать исключение, но я не думаю, что typeof(T) может генерировать.

Wyck 29.05.2023 15:59

Это зависит от того, что вы имеете в виду. Если вы создаете экземпляр T (ваш var x = new T();), а затем сразу после написания

Type t1 =  x.GetType();

и

if (t1 == typeof(T)) {... } // probably always true by definition

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

var x = new T();
var t1 = x.GetType(); // T 
...
x = new R();
...
bool chk1 = t1 == typeof(T); // true;
t1 = x.GetType(); // R
bool chk2 = t1 == typeof(T); // false

Мне непонятно, почему вы выдвинули гипотезу о существенно другом наборе кода, когда я дал конкретное (действительное) выражение, о котором я спрашивал?

Brondahl 29.05.2023 15:47

В универсальном методе Foo<T> where T : new() ... всегда ли верно это выражение?

typeof(T) == new T().GetType()

К сожалению нет. Для ссылочных типов (включая ссылочные типы, допускающие значение NULL) с конструкторами по умолчанию — да, но это не относится к типам значений, допускающим значение NULL.

Где T — это int? или DateTime? или любой другой тип значения, допускающий значение NULL, результат new T() равен нулю. Вызов GetType() на null, конечно же, приведет к NullReferenceException. Но попробуем другое:

static Type? WhichType<T>(T value) => value?.GetType();

Это не вызовет исключение, но может вернуть null. Теперь давайте попробуем:

var type1 = WhichType<int?>(0);
var type2 = WhichType((int?)0);

Поскольку типы значений, допускающие значение NULL, обрабатываются компилятором C# особым образом, не совсем ясно, будет ли результат вызова GetType() для типа значения, допускающего значение NULL, возвращать внутренний тип, и это имеет некоторый смысл. К сожалению, это не очень поможет вам, если кто-то вызовет ваш общий метод с неправильным типом.

И если вам интересно, это работает с любым типом значения, а не только с примитивами значений:

public struct TestType { }

var type1 = WhichType<DateTime?>(DateTime.Now);
var type2 = WhichType<TestType?>(new TestType());

Это может быть проблемой, когда вы пытаетесь сравнить тип значения с ожидаемым типом, где T — это тип значения, допускающий значение NULL. В этом случае вам нужно использовать немного кода, чтобы разобраться.

var targetType = typeof(T);
if (targetType.IsConstructedGenericType &&
    targetType.GetGenericTypeDefinition() == typeof(Nullable<>)
)
    targetType = Nullable.GetUnderlyingType(targetType);

Это при необходимости развернет Nullable<> из внешнего типа, что позволит вам сравнить его с типом экземпляра объекта.

Другие вопросы по теме