2010-07-21 3 views
6

Как известно, объекты C# имеют указатель на их тип, поэтому при вызове GetType() он проверяет этот указатель и возвращает реальный тип объекта. Но если я это сделать:Что происходит, когда вы делаете GetType()?

A objA = new A(); 
object obj = (object)objA; 
if (obj.GetType() == typeof(object)) ; // this is true 

Но что здесь происходит object obj = (object)objA;? Создает ли он какой-то ссылочный объект, который ссылается на objA, но имеет указатель на тип object, или это совершенно новый объект, который просто указывает на те же свойства, поля и т. Д. Как objA? Конечно, теперь вы можете получить доступ к обоим объектам, и они будут иметь другой тип, но указывают на одни и те же данные. Как это работает?

Другой вопрос: является ли GetType() гарантией возврата фактического типа объекта? Например, скажем, существует метод с сигнатурой void Method(object sender) и мы передаем объект типа A в качестве параметра. Будет sender.GetType() тип возврата A, или object? И почему?

Другое дело, что вы можете сделать (A)obj, и он будет работать. Как теперь CLR, что obj был когда-то типа A?

Был бы рад, если бы кто-то мог сломать его немного яснее, чем «C# через CLR».

Обновление. Мой плохой, должен был запустить код перед отправкой вопроса. Итак, если GetType() действительно всегда возвращает реальный тип, то все остальные вопросы становятся ясными.

+11

Ваш вопрос основан на совершенно ложном предположении. Строка с надписью «Это верно» неверна. Попробуйте написать небольшую программу, которая фактически компилируется и запускается, если вы мне не верите. GetType() всегда возвращает * фактический тип времени выполнения объекта. Все ваши вопросы основаны на неверном предположении, что тип времени компиляции имеет к этому какое-то отношение. Это не. –

+0

@ Эрик, ну, ты прав, и это то, что я всегда думал, отвлекся от какого-то кода, который по-другому ведет себя в проекте, и я плохой. –

ответ

22

Как известно, объекты C# имеют указатель на их тип, поэтому при вызове GetType() он проверяет этот указатель и возвращает реальный тип объекта.

Исправить.

, если я это сделать:

class A {} 
class P 
{ 
    public static void Main() 
    { 
     A objA = new A(); 
     object obj = (object)objA; 
     bool b = obj.GetType() == typeof(object) ; // this is true 
    } 
} 

Нет, это неверно. Попробуй!

Но что происходит здесь объект obj = (объект) objA ;?

Ссылка, которая находится в objA, копируется в переменную obj. (Если A не является типом значения, в этом случае он боксировал и ссылку на поле копируется в OBJ.)

ли это создать какое-то эталонный объект, который ссылается на objA, но имеет указатель типа для объекта или это совершенно новый объект, который просто указывает на одни и те же свойства, поля и т. д. как objA?

Ни то, ни другое. Он копирует ссылку, период. Он полностью не изменился.

Конечно, вы можете получить доступ к обоим объектам сейчас, и они будут иметь другой тип, но указывают на одни и те же данные. Как это работает?

Это не так. Вопрос основан на предположении, которое является ложным. У них не будет разных типов. Это одна и та же ссылка. Переменные имеют разные типы, но это не имеет значения; вы не задаете эту переменную для своего типа, вы запрашиваете у нее содержание.

is GetType() гарантированно возвращает фактический тип объекта?

Для ваших целей да. Есть неясные ситуации, связанные с COM-взаимодействием, где это не так.

Например, существует метод с сигнатурой void Method (отправитель объекта), и мы передаем объект типа A в качестве параметра. Будет ли sender.GetType() возвращать тип A или объект?

Тип A.

и почему?

Потому что это тип объекта.

Другое сложное дело в том, что вы можете сделать (A) obj, и он будет работать. Как CLR теперь, когда obj был когда-то типа A?

Компилятор C# генерирует инструкцию castclass. Команда castclass выполняет проверку времени выполнения, чтобы убедиться, что ссылка на объект реализует желаемый тип. Если это не так, CLR генерирует исключение.

+0

Eric, Из интереса, как я могу различать тип среды переменной от типа объекта, на который он ссылается? Разве не существует двух уровней/фаз системы типов? т. е. тип времени компиляции (используется для создания ошибок для таких вещей: ((object) mystring) .Substring()) и тип выполнения (из GetType()), используемый для отражения. Когда компиляция завершается неудачно, это происходит из-за проверки типа времени компиляции (т. Е. Вообще не проверяет тип выполнения), поэтому не использует как переменные, так и типы экземпляров как таковые). Является ли собственный тип переменной (а не тип вещей, на которые он ссылается), только манифест во время компиляции? –

+0

Извините, когда я говорю «различать», я должен сказать «различать во время исполнения через отражение». –

+1

@Andrew: тип переменной известен во время компиляции компилятором C# и во время выполнения верификатором CLR. Верификатор проверяет, что код проверен безопасным типом, гарантируя, что никакой переменной никогда не присваивается значение, несовместимое с его типом. Если ваш вопрос «я могу задуматься о типе локальной переменной с использованием отражения», нет, вы не можете, потому что * локальные переменные не отображаются отражением *. Вы можете, конечно, задуматься о типе поля или формальном параметре. –

Смежные вопросы