あなたの方法が実際にあった場合:
public MyTestClass1 Method()
{
Test e = Test.test1;
/*some code*/
var omyTestClass1 = new MyTestClass1(ref e);
/*some code*/
e = Test.test2;
/*some code*/
e = Test.test3;
return omyTestClass1;
}
返された値には、スタック上にあった値型への参照が含まれていますが、現在はありません。そのフィールドにアクセスしようとすると、何でも取得できます。
さらに悪いことに、そのリファレンスに書いたらどうなるでしょうか? その参照がすべての時間をレジスターに費やすのではなく、実際の呼び出しスタックに格納されていた場合 (そして、それを参照するクラスにフィールドがあったという事実自体が、それがあります)、今そこにあるのは何ですか?オブジェクトへの参照である可能性があります。返送先住所になる可能性があります。それに書き込みを行うと、奇妙なファンダンゴ・オン・ザ・コアのバグが発生する可能性があり、おそらく書き込み後しばらくしてからデバッグが困難になる可能性があります。
私たちが持っている基本的な保証の一部を失うことになります。その値を書き込んだ後は、ほぼすべてのコードが奇妙な方法で失敗する可能性があります。
この時点で注目に値するのは、C++ と .NET 自体 (つまり、C# ではできないものを含む .NET でできることすべて) は、ローカル参照を許可し、ref の戻り値を許可しないということです。田畑。
最も近いのは、ラムダおよび匿名メソッドで発生するキャプチャです。ここでは、ローカルはスタックではなくヒープに保存され、ライブによってキャプチャされたラムダが続く限り生き続けることができます (最後のものが収集されたときに収集されます)。これを使用して、オブジェクト内のローカルとして開始されたものへの参照を維持できます。
または、値型をラップするために必要な作業を行うクラスを使用できます。たとえば、同様の必要性があったときに使用したものを次に示します。
public sealed class SharedInt
{
private int _value;
/// <summary>Creates a new SharedInt with a value of zero.</summary>
public SharedInt(){}
/// <summary>Creates a new SharedInt.</summary>
/// <param name="value">The initial value of the object.</param>
public SharedInt(int value)
{
_value = value;
}
/// <summary>Returns the value of the SharedInt.</summary>
public int Value
{
get { return _value; }
}
/// <summary>Returns the value of the SharedInt.</summary>
/// <param name="ri">The SharedInt to cast.</param>
/// <returns>An integer of the same value as the SharedInt.</returns>
public static implicit operator int(SharedInt ri)
{
return ri._value;
}
/// <summary>Atomically increment the value of the SharedInt by one.</summary>
/// <returns>The new value.</returns>
public int Increment()
{
return Interlocked.Increment(ref _value);
}
/// <summary>Atomically decrement the value of the SharedInt by one.</summary>
/// <returns>The new value.</returns>
public int Decrement()
{
return Interlocked.Decrement(ref _value);
}
/// <summary>Atomically add a value to the SharedInt.</summary>
/// <param name="addend">The number to add to the SharedInt.</param>
/// <returns>The new value.</returns>
public int Add(int addend)
{
return Interlocked.Add(ref _value, addend);
}
/// <summary>Atomically replace the value of the SharedInt, returning the previous value.</summary>
/// <param name="value">The number to set the SharedInt to.</param>
/// <returns>The old value.</returns>
public int Exchange(int value)
{
return Interlocked.Exchange(ref _value, value);
}
/// <summary>Atomically subtract a value from the SharedInt.</summary>
/// <param name="subtrahend">The number to subtract from the SharedInt.</param>
/// <returns>The new value.</returns>
public int Subtract(int subtrahend)
{
return Interlocked.Add(ref _value, -subtrahend);
}
}
int
私はあなたが必要としないかもしれないいくつかの原子性保証が必要であり、同様にあなたが必要とするものを必要としないかもしれませんが、異なるクラス内から同じ値を処理できる手段として完全にうまく機能しました。
毎回プロパティを調べても構わない場合は、より汎用的なバージョンを実行できます。
public class TypedBox<T> where T : struct
{
public T Value;
}
フィールドを公に公開することにはかなりの欠点があります (これが、私たちが一般的にそうしない理由です) 。またはパラメータとしてValue
。ref
out