プロパティを「out」または「ref」パラメーターとして渡すことはできますか?
例えば
Person p = new Person();
. . .
public void Test(out p.Name);
プロパティを「out」または「ref」パラメーターとして渡すことはできますか?
例えば
Person p = new Person();
. . .
public void Test(out p.Name);
短い回答で申し訳ありませんが、いいえ、C# 言語仕様では許可されていません。
別の質問に対するこの回答を参照して、試してみるとどうなるかを確認してください。また、制限を回避するために、プロパティを単にパブリック フィールドにするべきではない理由も示しています。
お役に立てれば
編集:なぜですか?
実際に変数のアドレス (またはメモリ内の場所) を渡しているout
orパラメーターに変数を渡します。ref
関数内では、コンパイラは変数が実際にどこにあるかを認識し、そのアドレスに値を取得して書き込みます。
プロパティは値のように見えますが、実際には、それぞれが異なるシグネチャを持つ一対の関数です。したがって、プロパティを渡すには、実際には get 用と set 用の 2 つの関数ポインターを渡す必要があります。
それは、変数のアドレスとはまったく異なるものを関数に渡すことです
つまり、1 つの変数アドレス v の 2 つの関数ポインターです。
更新
なぜ C# は私たちのためにこれを処理しないのですか?
私はエリック・リッパートではありませんが、その理由を試してみます
呼び出している関数のシグネチャは何ですか?
そのまま呼び出すvoid MyFn(ref int i)
必要があるとしましょう。それとも、プロパティも許可するように変更する必要がありますか? これがかなり役に立たないような構文に変更された場合void MyFn(prop_ref int i)
、特別な prop_ref 修飾子で記述されていないライブラリ関数またはサードパーティ コードにプロパティを渡すことはできません。とにかく、あなたはそれが違うべきではないことを示唆していると思います。
ここで、COM 関数または WinAPI 呼び出しにパスを渡し、(つまり、.net の外部で、ref によって) アドレスを渡すとしMyFn
ます。それがプロパティの場合、どうやってアドレスを取得しますか? プロパティの下に、アドレスを取得する実際の int がない場合があります。VB.Net と同じことをしていますか?i
i
i
Vb.Net コンパイラは、プロパティが ByRef 引数としてメソッドに渡されたときに検出します。その時点で、変数を宣言し、プロパティを変数にコピーし、変数を ref で渡し、メソッドが呼び出された後、変数をプロパティにコピーして戻します。すなわち
MyFunc(myObject.IntProperty)
になる
Dim temp_i As Integer = myObject.IntProperty
MyFunc(temp_i)
myObject.IntProperty = temp_i
プロパティの副作用はMyFunc
、返されるまで発生しません。これにより、あらゆる種類の問題が発生し、非常に微妙なバグが発生する可能性があります。
私の謙虚な意見では、この問題に対する Vb.Net ソリューションも壊れているため、それを答えとして受け入れるつもりはありません。
C# コンパイラはこれをどのように処理すべきだと思いますか?
他の人は、C# ではこれを行うことができないと説明しています。VB.NET では、オプション strict/explicit on を使用しても、これを行うことができます。
Option Strict On
Option Explicit On
Imports System.Text
Module Test
Sub Main()
Dim sb as new StringBuilder
Foo (sb.Length)
End Sub
Sub Foo(ByRef x as Integer)
End Sub
End Module
上記のコードは、次の C# コードと同等です。
using System.Text;
class Test
{
static void Main()
{
StringBuilder sb = new StringBuilder();
int tmp = sb.Length;
Foo(ref tmp);
sb.Length = tmp;
}
static void Foo(ref int x)
{
}
}
個人的には、C# にこれがないことを嬉しく思います。特に、パラメーターがメソッド内で設定されているのに例外がスローされる場合、プロパティの値に関して、非常に混乱しています。
編集:要求に応じて、プロパティを渡すことを信じている理由についての私の推論は、水を濁らせます。通常の変数を参照渡しすると、その変数はメソッド内で参照されるたびに評価されます。何らかの理由で値が変更された場合 (たとえば、メソッド内の他の作業の副作用として)、その変更はメソッドですぐに表示されます。VB.NET で参照によってプロパティを渡す場合は、そうではありません。プロパティの getter が 1 回呼び出され、次にプロパティの setter が 1 回呼び出されます。「ここにプロパティがあります-パラメータを使用するたびにそこから取得および設定します」を渡しているわけではありません。
以下は、フィールドを渡す場合と .NET でまったく単純なプロパティを渡す場合の結果が大きく異なる完全な例です。
Option Strict On
Option Explicit On
Imports System.Text
Class Test
Dim counter as Integer
Property CounterProperty As Integer
Get
Return counter
End Get
Set (ByVal value as Integer)
counter = value
End Set
End Property
Sub Increment
counter += 1
End Sub
Shared Sub Main()
Dim t as new Test()
Console.WriteLine("Counter = {0}", t.counter)
t.Foo(t.counter)
Console.WriteLine("Counter = {0}", t.counter)
t.CounterProperty = 0
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
t.Foo(t.CounterProperty)
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
End Sub
Sub Foo(ByRef x as Integer)
x = 5
Increment
Increment
Increment
x += 1
End Sub
End Class
.Net-Fiddle: https://dotnetfiddle.net/ZPFIEZ (フィールドとプロパティの結果が異なります)