В чем разница между System.Type и System.RuntimeType в C #?

89

Сегодня я пытался провести несколько тестов по соглашению и получить все типы в сборке (путем вызова Assembly.GetTypes()), когда я наткнулся на что-то:

System.RuntimeType:[First.Namespace.FirstClass]

Всякий раз, когда я пытаюсь сравнить этот тип с typeof(FirstClass), они не равны. Итак, когда я пытаюсь найти все типы, содержащиеся FirstClassв качестве универсального параметра, я их не нахожу.

В чем разница между System.RuntimeTypeи System.Type?

Есть ли способ решить мою проблему?

Эдгар Гонсалес
источник
6
Можете ли вы предоставить небольшую программу, демонстрирующую проблему, с которой вы столкнулись?
Эрик Липперт,
Я собирался, но уже получил ответ: P
Эдгар Гонсалес

Ответы:

108

System.RuntimeType- это конкретный класс, производный от абстрактного базового класса System.Type. Поскольку System.RuntimeTypeне является общедоступным, вы обычно встретите его экземпляры как System.Type.

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

string str = string.Empty;
Type strType = str.GetType();
Type strTypeType = strType.GetType();
strType.ToString();     // returns "System.string"
strTypeType.ToString(); // returns "System.RuntimeType"

Например, в этом сообщении в блоге кто-то пытается получить тип столбца в базе данных, делая что-то вроде этого:

object val = reader.GetFieldType(index);
Type runtimeType = val.GetType();
PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
Type type = (Type)propInfo.GetValue(val, null);

Поскольку val уже является объектом Type, val.GetType () вернет другой объект Type, представляющий тип, System.RuntimeTimeпоскольку это конкретный тип, используемый для представления объекта исходного типа. Затем сообщение в блоге показывает некоторые ненужные уловки с отражением, чтобы получить тип исходного объекта типа, когда на самом деле все, что требовалось, было:

Type type = reader.GetFieldType(index) as Type;

Поэтому, если ваш Typeобъект сообщает, что он представляет собой System.RuntimeType, убедитесь, что вы случайно не вызвали GetType()тип, который у вас уже есть.

Эргвун
источник
Первый фрагмент кода проверяет только, является ли объект экземпляром - он Typeвернет true, даже если вы пройдете typeof(int). Второй фрагмент кода не подходит для сравнения typeof(string).GetType()и typeof(Type).
Марк Сидаде
Это именно то, что я искал! Я нашел сообщение Томаса Данекера, но не сообщение Дугала Белла
Эдгар Гонсалес
1
@Mark Cidade. Хорошо подмечено, спасибо. Сделайте фиксированный ответ, чтобы он был более полезным, надеюсь, проясняя любую путаницу, которую я внес, цитируя это сообщение в блоге.
Ergwun
@ Эдгар Гонсалес: Это сообщение в блоге, на которое я ссылался, на самом деле вводило в заблуждение. См. Мой обновленный ответ для получения дополнительной информации.
Ergwun
4

Из ответа Томаса Данекера на тему « Различия между System.Type и System.RuntimeType » :

System.Type - абстрактный базовый класс. CLR имеет конкретную реализацию во внутреннем типе System.RuntimeType. Из-за этого typeof (string) .GetType () возвращает RuntimeType, но typeof (Type) возвращает нормальный Type. Использование метода .Equals фактически создает объект .ReferenceEquals, который возвращает false. Чтобы получить ожидаемые результаты, вы можете использовать type.IsInstanceOfType (element). Это также вернет истину, если элемент имеет производный тип. Если вы хотите проверить точный тип, желаемым результатом будет возвращаемое значение false вашего метода. Вы также можете использовать checkType (arrayType, Type.GetType ("System.RuntimeType")) для проверки RuntimeType.

Джон Сондерс
источник
1
"действительно делает" - Можем ли мы получить грамматическую поправку. Это похоже на суть всего, и это не имеет смысла.
N73k
2

Вкратце...

    "".GetType().ToString()           == "System.String"

    "".GetType().GetType().ToString() == "System.RuntimeType"

Сейчас я думаю о том, что System.Typeэто базовый тип для типа, который представляет результаты запроса типа объекта во время выполнения, а именно System.RuntimeType. Итак, когда вы запрашиваете тип объекта, как, "".GetType(), экземпляр System.TypeВозвращается это потомок, System.RuntimeType. На самом деле, следовало ожидать, что и typeof(System.Type).GetType()должно быть System.RuntimeType, но я думаю, что фреймворк специально предотвращает эту ... симметрию.

Джордж
источник