14

outorパラメータに割り当てを行うrefと、その値は呼び出し元によって提供された参照にすぐに割り当てられますか? または、メソッドが戻るときにoutandパラメータ値が参照に割り当てられますか? 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?
}
4

2 に答える 2

26

refパラメータとパラメータを使用すると、呼び出し元が渡した実際の参照をメソッドで処理できるためout、これらの参照に対するすべての変更は、制御が返されるとすぐに呼び出し元に反映されます。

これは、上記の例を意味し (ArgumentExceptionコースをキャッチする場合)、両方outValueともrefValue2 に設定されます。

と はIL レベルでは同一の概念であることに注意することも重要です。メソッドが戻る前にその値を設定する必要があるという特別なルールを適用するのは、C# コンパイラoutだけです。したがって、CLR の観点からすると、同じセマンティクスを持ち、同じように扱われます。refoutoutValuerefValue

于 2010-01-07T23:26:17.363 に答える
14

アンドリューは正しいです。いくつかの詳細を追加するだけです。

まず、out/ref パラメーターの正しい考え方は、変数のエイリアスであるということです。つまり、メソッド M(ref int q) があり、それを M(ref x) と呼ぶと、q と x はまったく同じ variable の 2 つの異なる名前になります。変数は格納場所です。qに何かを保存すると、xにも保存されます。これらは同じ場所の2つの異なる名前であるためです。

第二に、あなたが説明している代替手段は、「コピーイン/コピーアウト」参照と呼ばれます。このスキームには 2 つの保存場所があり、関数呼び出しの開始時に 1 つの内容がコピーされ、完了時にコピーされて戻されます。お気づきのように、コピーインコピーアウトのセマンティクスは、例外がスローされたときのエイリアス参照のセマンティクスとは異なります。

また、次のような奇妙な状況でも異なります。

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

...

M(ref x, ref x);

エイリアシングでは、x、q、および r はすべて同じ保存場所であるため、これは 20 を出力します。左から右または右から左。

最後に、私の記憶が正しければ、式ツリーの実装には、参照パラメータにコピーインコピーアウトのセマンティクスを実際に実装する、まれで奇妙なシナリオがあります。そのコードを見直して、それらのシナリオが正確に何であるかを思い出すことができるかどうかを確認する必要があります。

于 2010-01-08T16:45:53.733 に答える