ByRefとByValの明確化



Byref Vs Byval Clarification



解決:

参照と値型の概念を混同していると思いますByVal対。ByRef。それらの名前は少し誤解を招くかもしれませんが、それらは直交する問題です。

VB.NETのByValは、指定された値のコピーが関数に送信されることを意味します。値型の場合(整数、シングルなど)これにより、値の浅いコピーが提供されます。より大きなタイプでは、これは非効率的です。ただし、参照型については(文字列、クラスインスタンス)参照のコピーが渡されます。コピーがミューテーションでパラメータに渡されるため=呼び出し元の関数には表示されません。



VB.NETのByRefは、元の値への参照が関数(1)に送信されることを意味します。元の値が関数内で直接使用されているようです。次のような操作=は元の値に影響し、呼び出し元の関数にすぐに表示されます。

ソケットは参照型(読み取りクラス)であるため、ByValは安いです。コピーを実行しますが、インスタンスのコピーではなく、参照のコピーです。



(1)VB.NETは実際にはコールサイトでいくつかの種類のByRefをサポートしているため、これは100%真実ではありません。詳細については、ブログエントリを参照してください ByRefの多くのケース



それを覚えておいてください ByValは引き続き参照を渡します。 違いは、参照のコピーを取得することです。

したがって、オーバーロードされたコンストラクターで、System.Net.Sockets.Socketのインスタンスへの参照を受け入れています。



はい、でもあなたがそれを求めた場合も同じことが言えます代わりにByVal。違いはByValを使用すると、参照のコピーを取得できます—新しい変数があります。とByRef、それは同じ変数です。

メモリ内のインスタンスがコピーされることは私の理解です

いいえ。参照のみがコピーされます。したがって、あなたはまだ 同じインスタンス。

これをより明確に説明するコード例を次に示します。

Public Class Foo Public Property Bar As String Public Sub New(ByVal Bar As String)Me.Bar = Bar End Sub End Class Public Sub RefTest(ByRef Baz As Foo)Baz.Bar = 'Foo' Baz = new Foo( 'replaced' )End Sub Public Sub ValTest(ByVal Baz As Foo)Baz.Bar = 'Foo' Baz = new Foo( 'replaced')End Sub Dim MyFoo As New Foo( '-')RefTest(MyFoo)Console.WriteLine(MyFoo。 Bar) ''#出力が置き換えられましたValTest(MyFoo)Console.WriteLine(MyFoo.Bar) ''#出力Foo 

私の理解では、ByVal / ByRefの決定は、(スタック上の)値型にとって本当に最も重要であるということです。 ByVal / ByRefは、参照型がSystem.Stringのように不変でない限り、(ヒープ上の)参照型に対してほとんど違いがありません。可変オブジェクトの場合、オブジェクトByRefまたはByValを渡すかどうかは関係ありません。メソッドでオブジェクトを変更すると、呼び出し元の関数が変更を確認します。

ソケットは変更可能であるため、任意の方法で渡すことができますが、オブジェクトへの変更を保持したくない場合は、自分でディープコピーを作成する必要があります。

Module Module1 Sub Main()Dim i As Integer = 10 Console.WriteLine( 'int {0}の初期値:'、i)ByValInt(i)Console.WriteLine( 'int {0}のbyval値の後:'、i )ByRefInt(i)Console.WriteLine( 'int {0}のbyref値の後:'、i)Dim s As String = 'hello' Console.WriteLine( 'str {0}の初期値:'、s)ByValString( s)Console.WriteLine( 'str {0}のbyval値の後:'、s)ByRefString(s)Console.WriteLine( 'str {0}のbyref値の後:'、s)Dim sb As NewSystem.Text。 StringBuilder( 'hi')Console.WriteLine( '文字列ビルダーの初期値{0}:'、sb)ByValStringBuilder(sb)Console.WriteLine( '文字列ビルダーのbyval値の後{0}:'、sb)ByRefStringBuilder(sb )Console.WriteLine( '文字列ビルダー{0}のbyref値の後:'、sb)Console.WriteLine( 'Done ...')Console.ReadKey(True)End Sub Sub ByValInt(ByVal value As Integer)value + = 1 End Sub Sub ByRefInt(ByRef value As Integer)value + = 1 End Sub Sub ByValString(ByVal value As String)value + = 'world!' End Sub Sub ByRefString(ByRef value As String)value + = 'world!' End Sub Sub ByValStringBuilder(ByVal value As System.Text.StringBuilder)value.Append( 'world!')End Sub Sub ByRefStringBuilder(ByRef value As System.Text.StringBuilder)value.Append( 'world!')End Sub End Module