Когда значение C# или 'касательно' параметра, на самом деле возвращенного вызывающей стороне?

Когда я делаю присвоение на out или ref параметр, является значением, сразу присвоенным ссылке, обеспеченной вызывающей стороной, или out и ref значения параметров присвоили ссылкам, когда метод возвращается? Если метод выдает исключение, значения возвращаются?

Например:

int callerOutValue = 1;
int callerRefValue = 1;
MyMethod(123456, out callerOutValue, ref callerRefValue);

bool MyMethod(int inValue, out int outValue, ref int refValue)
{
    outValue = 2;
    refValue = 2;

    throw new ArgumentException();

    // Is callerOutValue 1 or 2?
    // Is callerRefValue 1 or 2?
}
14
задан Zach Johnson 8 January 2010 в 07:30
поделиться

2 ответа

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

Это означает, что в вашем примере выше (если вы собирались поймать ArgumentException , конечно), ovalue и Refvalue будут установлены на 2.

Также важно отметить, что из и и являются идентичными концепциями на уровне IL - это только компилятор C #, который обеспечивает дополнительный правил Для этого требуется, чтобы способ установить его значение до возвращения. Таким образом, от перспективы CLR ovalue и Refvalue имеют идентичную семантику и обрабатываются так же.

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

Андрей правильный; Я просто добавлю пару дополнительных деталей.

Во-первых, правильный способ подумать о параметрах OUT / REF заключается в том, что они являются псевдонимами для переменных . То есть, когда у вас есть метод m (ref int q) и вызовите его m (ref x), q и x - это два разных имена для точно такой же переменной . Переменная - это место хранения; Вы храните что-то в Q, вы храняте его в X тоже, потому что они два разных имена для того же места.

Во-вторых, альтернатива, которую вы описываете, называется ссылками «Копировать в / копировать». В этой схеме есть два места хранения, и содержимое одного скопированы на начало вызова функции и копировали обратно, когда его сделано. Как вы отмечаете, семантика копирования копирования отличается от семантики ссылок на псевдоним, когда исключены исключения.

Они также различны в причудливых ситуациях, такими, как это:

void M(ref int q, ref int r)
{  
  q = 10;
  r = 20;
  print (q);
}

...

M(ref x, ref x);

в псевдонимах, x, q и r - это одно и то же место для хранения, поэтому эти отпечатки 20. В ссылке на копирование в копировании это будет печатать 10 И окончательная стоимость X будет зависеть от того, остался ли копирование вправо или направо налево.

Наконец, если я правильно вспомнил, есть редкие и странные сценарии в реализации деревьев выражения, где мы фактически реализуем семантику для копирования в параметрах REF. Я должен просмотреть этот код и посмотреть, смогу ли я вспомнить, что именно эти сценарии.

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

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