На этой неделе я работал над некоторым основанным на отражении кодом, и во время поблочного тестирования нашел неожиданное условие: указатели являются ссылочными типами. Код C# typeof(int).MakePointerType().IsClass
возвраты true
.
Я зарегистрировался в своем просто прибывшем Аннотируемом Стандарте CLI, и конечно же, указатели ясно определяются как ссылочные типы.
Это было удивительно мне, произойдя из среды C++. Я только что предположил, что указатели будут типами значения.
Существует ли конкретная причина, почему типы указателей являются ссылочными типами и не оценивают типы?
Обновление (разъяснение)
При разговоре об указателях и ссылках, вещи часто становятся сбивающими с толку относительно "указателя" и "pointee". Таким образом, вот некоторое разъяснение.
Типы могут быть ссылочными типами или оценить типы, но переменные несколько отличаются. (Извините, у меня не было шанса прочитать мой Стандарт CLI, таким образом, терминология и понятия могут быть неправильными - исправляют меня!)
Учитывая этот код (понятия локальной переменной для ссылочных типов):
var x = new MyClass();
var y = x;
Переменные x
и y
не на самом деле ссылочные типы, но они - ссылки на объект, который является ссылочным типом (MyClass
ссылочный тип). Другими словами, x
и y
не экземпляры ссылочного типа; они только обращаются к экземпляру ссылочного типа.
Учитывая этот код (понятия локальной переменной для типов значения):
var x = 13;
var y = x;
Переменные x
и y
типы значения экземпляров (или, по крайней мере, действуйте как, они - экземпляры).
Таким образом мы приходим к этому коду:
var i = 13;
var x = &i;
var y = x;
Если тип указателя является ссылочным типом, то это - то, как я интерпретирую оператор x = &i
:
int*
создается, указывая i
.x
ссылка на этот экземпляр указателя.y = x
выполняется, ссылка копируется. Оба y
и x
обратитесь к тому же экземпляру объекта указателя.Возможно, я абсолютно неправ в этой интерпретации.
Происходя из среды C++, имело бы больше смысла мне для указателей быть типами значения, таким образом, оператор x = &i
просто присваивает адрес i
к экземпляру типа значения x
, и y = x
копии то значение адреса в y
. Никакой "объект указателя" не был бы создан на "куче".
typeof (int) .MakePointerType (). IsPointer
кажется, есть различие.
Это всего лишь теория, но связано ли это с тем фактом, что из-за системы сбора мусора и уплотнения кучи указатели должны корректироваться при перемещении объектов в памяти. Создав управляемые указатели ссылочных типов, они могут быть перенаправлены так же, как и любые другие ссылки, вместо того, чтобы делать их особым случаем.
Обновление
Отличная статья Веснера Мойса: « Указатели НЕ ДОКУМЕНТИРОВАНЫ ».
В статье он описывает, как управляемые указатели корректируются во время сжатия кучи.
Это ссылочные типы, потому что они не содержат фактического значения целевого объекта: как и ссылки, они просто «указывают» на целевой объект.
Примите во внимание:
MyClass x = new MyClass();
Здесь MyClass - это ссылочный тип, и если вы просматриваете отражение, x будет называться ссылочным типом. Но под капотом x на самом деле является указателем.