15

かなり単純な質問 (だと思います) ですが、まだ答えが見えていないようです。一部の値は値を介して渡され (int や long など)、他の値は関数に渡すときに参照によって渡されます (文字列など)。

私のプログラムでは、バックグラウンドで長いプロセスを実行しているときに GUI がロックしないように、バックグラウンド ワーカーを使用しています。別のファイルから UI スレッドにデータを戻す必要があるため、そのためにイベントを使用しています。ここで、文字列の配列のリストを GUI スレッドに送り返してそこで処理する必要がありますが、それがどのように処理されるか心配です。基本的に、ワーカー スレッドには、リストをいっぱいにするループがあり、イベント ハンドラーを介してそれを GUI に送り返し、それをクリアして、次のループのパスでリストをいっぱいにして、再び開始できるようにします。

これを行うときに、リストが参照渡しの場合、UI スレッドでは、ワーカー スレッドがまだバックグラウンドでリストをクリアしているため、読み取り中にクリアされるのではないかと心配しています。この場合、通過する方がはるかに望ましいので、それを強制する方法を見つけることができます(ホルダー配列にコピーするか、ミューテックスなどを追加します)が、イベント引数が経由で渡されるかどうかを知るのは良いことだと思いました一般的に参照または値ですか、それともメソッドと同じであり、引数が通常渡されるようにそれらを渡しますか?

4

4 に答える 4

22

一部の値は値を介して渡され (int や long など)、他の値は関数に渡すときに参照によって渡されます (文字列など)。

いいえ。デフォルトでは、すべてが値渡しされますが、参照型を使用している場合は、「すべて」が参照になります。その参照は値によって渡されます。それは参照渡しと同じではありません。詳細については、パラメーターの受け渡しに関する私の記事を参照してください。

outイベント引数はまったく同じです。対応するデリゲートがorrefパラメーターを使用しないと仮定すると、すべての参照が値で渡されます。

編集:あなたの懸念に対処するには:はい、イベント引数が変更可能で、別のスレッドで動作する場合は、最初にコピーを作成する必要があります...または、既存の参照を渡してから新しい (空) リストをワーカー スレッドに追加します。

于 2012-08-03T17:37:09.330 に答える
4

引数自体は、デフォルトで値渡しされます。ただし、型によっては、値または操作している実際の値への参照になる場合があります。

これは、一般に参照渡しとして知られているものとは異なることに注意してください。引数に実際に渡される値そのものがコピーされる (つまり、値渡し) ためです。ただし、メソッド内で参照されるオブジェクトを変更すると、その変更はメソッドの外部 (メソッドを呼び出したコード内) にも表示されるという点で同様です。

ここで、値渡しの場合、イベント引数について特別なことは何もありません。値がコピーされるか、参照のみがコピーされるかは、その型に完全に依存します。したがって、あなたが言ったようにintlong引数(およびその他の任意のstruct型)は値型であり、その他string(および任意のクラスインスタンス)は参照型です。

C#でも真の参照渡しが可能ですが、refキーワードが必要です。

于 2012-08-03T17:37:11.697 に答える
3

標準のイベント パターンでは、次の 2 つの参照が渡されます。

 void FormClosing(object sender, FormClosingEventArgs e) { ... }

これらの 2 つの参照は「値渡し」で渡されます。たとえば、を使用しsender = nullても、処理メソッド以外では効果がありません。

ただし、値を簡単に返すことができます。

void FormClosing(object sender, FormClosingEventArgs e)
{
    ...
    e.Cancel = true;  // this will pass back to the caller
}
于 2012-08-03T17:43:20.133 に答える
1

イベント引数は、引数の型とイベントハンドラーのデリゲートのシグネチャ( in 、 out または ref)に従って渡されます。クラスの場合は参照のコピーが渡され、構造体の場合は参照のコピーが渡されます。値のコピーが渡されます (署名で out または ref が指定されていないと仮定します)。

通常、イベント引数はクラス (通常はEventArgsから継承) であり、多くの場合、eventArgs.DoCancel などの値を呼び出し元に返すために使用されます。

于 2012-08-03T17:38:15.397 に答える