Касательно и в C# то же указатели в C++?

Мне нравится ответ Cohens, но более техническое определение: Ваш код называет библиотеку. платформа А называет Ваш код . Например, платформа GUI называет Ваш код через обработчики событий. Веб-платформа называет Ваш код через некоторую модель ответа запроса.

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

8
задан Bob Dylan 22 July 2009 в 18:46
поделиться

7 ответов

Они более ограничены. Вы можете сказать ++ на указателе, но не на ref или out .


EDIT Некоторая путаница в комментариях, чтобы быть абсолютно ясным: суть вот для сравнения с возможностями указателей. Вы не можете выполнить ту же операцию, что и ptr ++ , на ref / out , то есть сделать так, чтобы он адресовал соседнее место в памяти. Это правда (но здесь не имеет значения), что вы можете выполнить эквивалент (* ptr) ++ , но это будет для сравнения с возможностями значений , а не указателей.


Можно с уверенностью сказать, что они внутренне всего лишь указатели, потому что стек не t перемещается, а C # тщательно организован так, чтобы ref и out всегда ссылались на активную область стека.


EDIT Чтобы снова было абсолютно ясно (если это не было уже ясно из приведенного ниже примера), дело не в том, что ref / out может только указывать на стек. Дело в том, что , когда указывает на стек, правила языка гарантируют, что он не станет висящим указателем. Эта гарантия необходима (и здесь актуальна / интересна), потому что стек просто отбрасывает информацию в соответствии с выходами из вызова метода, без каких-либо проверок, чтобы гарантировать, что какие-либо источники ссылок все еще существуют.

И наоборот, когда ref / ] out относится к объектам в куче сборщика мусора it ' Неудивительно, что эти объекты могут оставаться в живых столько, сколько необходимо: куча сборщика мусора предназначена именно для хранения объектов в течение любого периода времени, необходимого для их источников перехода, и обеспечивает закрепление (см. пример ниже) для поддержки ситуаций. где объект не должен перемещаться с помощью сжатия GC.


Если вы когда-нибудь играли с взаимодействием в небезопасном коде, вы обнаружите, что ref очень тесно связан с указателями. Например, если COM-интерфейс объявлен так:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия превратит его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

куча сборщика мусора предназначена именно для сохранения объектов в течение любого периода времени, необходимого их источникам ссылок, и обеспечивает закрепление (см. пример ниже) для поддержки ситуаций, когда объект не должен перемещаться путем сжатия сборщика мусора.


Если вы когда-либо поиграйте с взаимодействием в небезопасном коде, вы обнаружите, что ref очень тесно связан с указателями. Например, если COM-интерфейс объявлен так:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия превратит его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

куча сборщика мусора предназначена именно для того, чтобы сохранять объекты в течение любого периода времени, необходимого их источникам ссылок, и обеспечивает закрепление (см. пример ниже) для поддержки ситуаций, когда объект не должен перемещаться путем сжатия сборщика мусора.


Если вы когда-либо поиграйте с взаимодействием в небезопасном коде, вы обнаружите, что ref очень тесно связан с указателями. Например, если COM-интерфейс объявлен так:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия превратит его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

и обеспечивает закрепление (см. пример ниже) для поддержки ситуаций, когда объект не должен перемещаться посредством сжатия GC.


Если вы когда-нибудь играли с взаимодействием в небезопасном коде, вы обнаружите, что ref очень тесно связан указателям. Например, если COM-интерфейс объявлен так:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия превратит его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

и обеспечивает закрепление (см. пример ниже) для поддержки ситуаций, когда объект не должен перемещаться посредством сжатия GC.


Если вы когда-нибудь играли с взаимодействием в небезопасном коде, вы обнаружите, что ref очень тесно связан указателям. Например, если COM-интерфейс объявлен так:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия превратит его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

если COM-интерфейс объявлен следующим образом:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия преобразует его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

если COM-интерфейс объявлен следующим образом:

HRESULT Write(BYTE *pBuffer, UINT size);

Сборка взаимодействия преобразует его в это:

void Write(ref byte pBuffer, uint size);

И вы можете сделать это, чтобы вызвать его (я считаю, что компонент COM-взаимодействия позаботится о закреплении массива):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

Другими словами, ref к первому байту дает вам доступ ко всему этому; очевидно, это указатель на первый байт.

10
ответ дан 5 December 2019 в 06:54
поделиться

Справочные параметры в C # могут использоваться для замены одного использования указателей, да. Но не все.

Другое распространенное использование указателей - это средство для итерации по массиву. Параметры Out / ref не могут этого сделать, поэтому нет, они не «такие же, как указатели».

6
ответ дан 5 December 2019 в 06:54
поделиться

На самом деле, я бы сравнил их со ссылками на C ++, а не с указателями. Указатели в C ++ и C являются более общей концепцией, и ссылки будут делать то, что вы хотите.

Все это, несомненно, указатели под крышками, конечно.

2
ответ дан 5 December 2019 в 06:54
поделиться

ref и out используются только с аргументами функции, чтобы указать, что аргумент должен передаваться по ссылке вместо значения. В этом смысле да, они чем-то похожи на указатели в C ++ (на самом деле больше похожи на ссылки). Подробнее об этом читайте в этой статье .

3
ответ дан 5 December 2019 в 06:54
поделиться

Хорошая вещь в использовании out заключается в том, что вам гарантировано, что элементу будет присвоено значение - в противном случае вы получите ошибку компиляции.

1
ответ дан 5 December 2019 в 06:54
поделиться

Короткий ответ - да (аналогичная функциональность, но не совсем тот же механизм). В качестве примечания: если вы используете FxCop для анализа кода, использование out и ref приведет к ошибке «Microsoft.Design» «CA1045: DoNotPassTypesByReference.»

1
ответ дан 5 December 2019 в 06:54
поделиться

В то время как сравнения находятся в поле зрения смотрящего ... Я говорю нет. 'ref' изменяет соглашение о вызовах , но не тип параметров. В вашем примере на C ++ d1 и d2 имеют тип int *. В C # они все еще являются Int32, они просто передаются по ссылке, а не по значению.

Между прочим, ваш код на C ++ этого не делает. На самом деле меняют местами входы в традиционном смысле. Обобщая это так:

template<typename T>
void swap(T *d1, T *d2)
{
    T temp = *d1;
    *d1 = *d2;
    *d2 = temp;
}

... не будет работать, если все типы T не будут иметь конструкторы копирования, и даже в этом случае будет гораздо более неэффективно, чем замена указателей.

1
ответ дан 5 December 2019 в 06:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: