Типы ссылок - можем ли мы увидеть реальную ссылку? - PullRequest
7 голосов
/ 11 января 2012

Разница между ссылочными типами и типами значений часто сбивает с толку новичков из-за непонимания того, что на самом деле содержит переменная типа значения. Мы знаем, что:

  • Типы значений хранят фактическое значение
  • Типы ссылок сохраняют только ссылку на объект

Можно ли проверить каждый тип переменной, чтобы увидеть значение или саму фактическую ссылку 1014 *? Хранится ли ссылка как кодированное значение? Я знаю, что ссылки могут быть переданы по значению, поэтому я предполагаю, что так.

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

Ответы [ 4 ]

10 голосов
/ 11 января 2012

Можно ли проверить каждый тип переменной, чтобы увидеть значение или саму фактическую ссылку?

Просто для пояснения, значение переменной ссылочного типа является ссылкой.Ссылка - это значение.

Ссылка - это разновидность значения, также как int - это разновидность значения.В отличие от int, ссылка - это значение, которое может быть скопировано только и разыменовано ;вы не можете наблюдать его значение непосредственно в C #, потому что это значение - деталь реализации сборщика мусора.

Хранится ли ссылка как кодированное значение?

Да, именно так.На практике ссылка - это 32- или 64-разрядное целое число (в зависимости от того, участвуете ли вы в 32- или 64-разрядном процессе), которое указывает на некоторую структуру, известную сборщику мусора как связанную с данными объекта, на который указывает ссылка.

Если вы хотите посмотреть ссылки напрямую, инструмент для этого - отладчик.Загрузите ваш код C # в отладчик, скомпилируйте его, запустите, достигните точки останова и посмотрите на состояние стека и регистров.С небольшим умом вы сможете определить, какие ячейки стека и регистры соответствуют каким локальным переменным.Местоположения, соответствующие локальным переменным типа значения, будут содержать значения;те из ссылочного типа будут содержать значения, похожие на указатели.Если вы исследуете эти указатели в окне памяти, вы будете искать структуры, поддерживаемые сборщиком мусора, которые описывают содержимое объекта.

5 голосов
/ 11 января 2012

Это, вероятно, один для Джона Скита, но у меня может быть другой угол:

Не волнуйтесь слишком много о как эти вещипредставлены в памяти.Если вы не прочитали всю спецификацию языка - кто это делает?- вам не нужно знать.В самом деле.Не надо запоминать, где хранятся данные - есть вероятность, что это зависит от реализации.

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

Вы действительно не хотите знать, что на самом деле содержит объявление типа.Поверь мне.То, что вы хотите знать, это как он ведет себя .

1 голос
/ 11 января 2012

Вы можете сделать это с unsafe кодом:

    unsafe
    static void Main(string[] args)
    {
        string s = "Hello";

        fixed (char* pc = s)
        {                
            IntPtr p = (IntPtr)pc;
            Console.WriteLine(p);   // here is your meaningless address 
        }            
    }
1 голос
/ 11 января 2012

Вы можете сделать это с закрепленным объектом довольно легко;

GCHandle gch=GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr AddressInMemory=gch.AddrOfPinnedObject();
...