18

ByRef と ByVal を選択する際に考慮すべきことは何ですか。

2 つの違いは理解できますが、ByRef がリソースを節約するかどうか、または .Net 環境でそれについて心配する必要があるかどうかは完全にはわかりません。

ある状況で機能が問題にならない場合、どのように 2 つのどちらかを決定しますか?

4

10 に答える 10

34

これについては、多くの誤った情報が飛び交っています。重要なことは、値型と参照型の違い、および値渡しと参照渡しの違いを理解していることです。

ほとんどの場合、値渡しが必要になります。参照渡しはほとんどの場合、「渡されたリストに何かを追加するだけでなく、複数の結果を返したい」ためのものです。参照渡しを使用するメソッドの典型的な例はInt32.TryParseで、戻り値は成功/失敗であり、解析された値は out パラメータによって「返されます」。

于 2008-11-14T14:28:02.270 に答える
15

デフォルトはすべての型の byValue ですが、値型ではなく「参照型」(クラス) に対する 2 つのオプションの意味を理解することが重要です。(構造体)。

参照型の場合、メソッドで参照型変数を宣言すると、その変数はメソッドのスタック フレーム内のメモリ位置になります。ヒープ上にはありません。その変数を (new または factory などを使用して) 初期化すると、ヒープ上に実際のオブジェクトが作成され、そのオブジェクトのアドレスがメソッド スタック フレームの宣言された参照変数に格納されます。

参照型を別のメソッド byVal に渡すと、呼び出し元のメソッド スタックに格納されているアドレスのコピーが作成され、その値 (ポインター アドレス) のコピーが呼び出されたメソッドに渡され、新しいメモリに格納されます。呼び出されたメソッド スタックのスロット。呼び出されたメソッド内では、新しく複製された変数がヒープ上の同じオブジェクトを直接指しています。したがって、それを使用すると、同じオブジェクトのプロパティを変更できます。ただし、元の参照変数 (呼び出しメソッド スタック上) が指すヒープ オブジェクトを変更することはできません。呼び出されたメソッドで私が書く場合

  myVar = new object();

呼び出し元のメソッドの元の変数は、新しいオブジェクトを指すように変更されていません。

参照型 byRef を渡す場合、呼び出し元のメソッド スタック (ヒープ上のオブジェクトへのポインターを含む) で宣言された変数へのポインターを渡します。したがって、それはオブジェクトへのポインターへのポインターです。これは、ヒープ上のオブジェクトを指す呼び出しメソッド スタック上のメモリ位置を指します。
したがって、呼び出されたメソッドの変数の値を変更すると、上記のように new object() に設定することで、呼び出しメソッドの変数への「参照」であるため、実際にどのオブジェクトを変更していますか呼び出しメソッドの変数が指しています。したがって、呼び出されたメソッドが戻った後、呼び出し元のメソッドの変数は、ヒープ上の同じ元のオブジェクトを指しなくなります。

于 2008-11-14T14:41:21.073 に答える
8

ByVal が「デフォルト」である必要があります。ByRef を使用する特別な理由がない限り使用してください。

于 2008-11-14T14:15:00.457 に答える
8

.net でオブジェクト ByVal を渡すと、オブジェクトのコピーは作成されず、ByRef よりも多くのリソースを消費しません。ポインターは引き続き関数に渡されます。ランタイムは、関数内のポインターを変更して別の値を返すことができないことを保証するだけです。オブジェクト内の値を変更することはできますが、それらの変更は関数の外部に表示されます。そのため、ByRef はめったに使用されません。返される実際のオブジェクトを関数で変更する場合にのみ必要です。したがって、出力パラメータです。

于 2008-11-14T14:29:39.960 に答える
5

パラメータが「出力」パラメータである場合にのみ、「ByRef」を使用します。それ以外の場合は、「ByVal」を使用してください。明示的に値を返すべきではないパラメーターに「ByRef」を使用することは危険であり、バグを簡単に生成する可能性があります。

于 2008-11-14T14:17:12.293 に答える
3

ByRefは絶対に使用しないでください。これは悪い習慣です。関数が(ByRefパラメーターを介して)複数の値を返すことを許可する典型的なユースケースにもそれを適用します。関数は、これらの複数の戻り値を含む構造化された応答を返す方がよいでしょう。関数がreturnステートメントを介してのみ値を返す場合は、より明確で明白になります。

于 2011-07-07T16:35:59.017 に答える
0

多くの混乱を単純化しようとします。基本的に 4 つの選択肢があります。

  1. 値型 byVal を渡す
  2. 値型 byRef を渡す
  3. オブジェクトをValで渡す
  4. Ref でオブジェクトを渡す

byRef を使うべきではないと言う人もいます。それらは技術的には正しいですが、確かなことが 1 つあります。neverという言葉は絶対に使用しないでください。システムをゼロから設計している場合は、byRef は絶対に避ける必要があります。それを使用すると、設計上の欠陥が明らかになります。ただし、既存のシステムでの作業では、優れた設計を実装するための柔軟性が十分に得られない場合があります。場合によっては、byRef を使用して譲歩する必要があります。たとえば、byRef を使用して 2 日で修正を完了できる場合は、byRef の使用を避けるためだけに車輪を再発明して同じ修正を得るのに 1 週​​間かかるよりも望ましい場合があります。

概要:

  1. 値型で byVal を使用する: 関数に値を渡します。これは、関数を設計するための推奨される方法です。
  2. 値型での byRef の使用: 関数から複数の値を返す場合に便利です。既存のシステムに複数の値を返す必要がある関数を作成している場合、これは 1 つの関数のためだけにオブジェクトを作成する (およびプロパティを設定し、破棄する) よりも優れています。
  3. オブジェクトで byVal を使用する: オブジェクトのポインターを関数に渡します。関数はオブジェクトを変更できます。
  4. オブジェクトで byRef を使用する: オブジェクトのポインターへのポインターを関数に渡します。呼び出し元が指しているオブジェクトを変更できます。これにより、見つけにくいバグが発生する可能性があり、それを使用する正当な理由が思いつきません。存在しないという意味ではありませんが、存在する場合はほとんどありません。
于 2016-03-17T13:54:05.347 に答える
0

特定の引数を ByRef としてマークすると、その引数に割り当てられた変数が **変更されることを関数のユーザーに示します。****

すべての引数にByRef を使用すると、どの変数が関数によって変更され、どの変数が読み取られるだけなのかを判断する方法がなくなります。(関数ソースの中をのぞくのは別として!)

于 2008-12-02T21:49:25.057 に答える
0
Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub
于 2015-10-02T11:17:11.930 に答える