2010-07-23 7 views
17

На этой неделе я работал над некоторым кодом на основе отражения, и во время модульного тестирования обнаружилось неожиданное условие: указатели являются ссылочными типами. Код C# typeof(int).MakePointerType().IsClass возвращает true.Почему ссылочные типы указателей?

Я проверил в моем только что установленном стандарте CLI, и, конечно же, указатели четко определены как ссылочные типы.

Это было удивительно для меня, исходя из фона C++. Я только что предположил, что указатели будут типами значений.

Существует ли конкретная причина, по которой типы указателей являются ссылочными типами, а не типами значений?

Update (осветление)

Когда речь идет о указателях и ссылках, вещи часто запутаться в отношении "указателя" и "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:

  1. Экземпляр типа int*, указывая на i.
  2. Поскольку указатели являются ссылочными типами, этот экземпляр создается в куче (при условии, что все ссылочные типы помещаются в кучу, деталь реализации).
  3. x - ссылка на этот экземпляр указателя.
  4. Экземпляр указателя в конечном итоге будет собран мусором, как и другие ссылочные типы.
  5. Когда выполняется y = x, ссылка копируется.Оба y и x относятся к тому же экземпляру объекта-указателя.

Возможно, я полностью ошибаюсь в этой интерпретации.

Исходя из C++ фон, было бы больше смысла для меня, для указателей, чтобы быть типами значений, поэтому оператор x = &i просто назначая адрес i к экземпляру типа значения x и y = x копии, значение адреса в y. В куче не будет создан «объект-указатель».

+2

Из документов CLR на Type.IsClass - Получает значение, указывающее, является ли тип классом; то есть не тип значения или интерфейс ». Технически тип указателя не наследует «System.Object», поэтому он не является объектом, типом значений или интерфейсом, а является классом в соответствии с документами. – thecoop

ответ

2

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

Я вынужден заключить: указатели (например, int *) are actually value types; тот факт, что их Type с возвращается true за IsClass является ошибкой в ​​спецификации. Я подозреваю, что никто этого не заметил, потому что получение типа указателя - очень редкая операция.

+0

Вы видели [docs] (http://msdn.microsoft.com/en-us/library/y31yhkeb (v = vs.110) .aspx)? В соответствии с этим: * В небезопасном контексте тип может быть типом указателя, типом значения или ссылочным типом *. Так вы не можете относиться к ним как к типу значений, так и к ссылочному типу? – nawfal

+0

Это имеет смысл. Но это не отвечает на мой вопрос: * почему ссылочные типы указателей (т. Е. Они возвращают 'true' из' IsClass')? * –

+0

См. Рисунок для еще одного противоречивого утверждения из [docs] (http: // msdn. microsoft.com/en-IN/library/2hf02550(v=vs.90).aspx). Указатели перечислены в ссылочных типах. – nawfal

0

Это ссылочные типы, поскольку они не содержат фактическое значение целевого объекта: точно так же, как ссылки, они просто «указывают на» целевой объект.

+1

Я обновил вопрос, чтобы быть более понятным по ссылке * types * vs. reference * variables *. –

-2

Рассмотрим:

MyClass x = new MyClass(); 

Здесь MyClass является ссылочным типом, и если вы смотрели через отражение, х будет называться ссылочный тип. Но, под капотом, x на самом деле является указателем.

+1

Тип указателя ('int *') - это совершенно другая сущность к нормальной ссылке на объект – thecoop

+1

@thecoop ссылка концептуально ничего не отличается от указателя. Оба содержат адрес в памяти некоторых других данных, будь то примитив 'int' или объект MyClass. Основное различие заключается в том, что ссылки обычно неизменяемы (сами ссылки, а не то, что они называют). – corsiKa

3

TypeOf (интермедиат) .MakePointerType(). IsPointer

кажется, что есть различие.

+1

Право; можно определить, является ли ссылочный тип указателем или нет. Мой вопрос в том, почему указатели являются ссылочными типами, а не типами значений (см. Обновленный вопрос). –

+1

CLR различает управляемые и неуправляемые типы указателей, см. 12.1.1.1 раздела I в спецификации clr.Управляемые указатели могут быть изменены (перемещены) GC. Я думаю, что это может быть причиной для них типов классов. – MaLio

+0

См. Также раздел 14.4 Раздел II - Специальные типы/типы указателей – MaLio

1

Это всего лишь теория, но имеет ли она какое-то отношение к тому факту, что из-за системы сбора мусора и уплотнения кучи указатели должны корректироваться при перемещении объектов в памяти. Путем создания ссылочных типов управляемого указателей они могут быть перенаправлены так же, как и любая другая ссылка, вместо того, чтобы делать их особым случаем.

Update

Отличная статья Wesner Моиса: "Pointers UNDOCUMENTED".

В статье описывается, как управляемые указатели корректируются во время уплотнения кучи.

+0

Я считаю, что указатели могут указывать только на закрепленные объекты - [см. MSDN ref] (http://msdn.microsoft.com/en-US/library/zcbcf4ta.aspx) , Однако я прочитаю эту статью; выглядит интересно! –

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