はい、そのコードは機能しますが、説明が必要です。なぜなら、機能しないコードの世界があり、これを知らない限り、それにつまずく可能性が高いからです。
忘れる前に:可変構造体は悪です。では、それはさておき、先に進みましょう。
簡単な例を見てみましょう。LINQPadを使用してこのコードを検証できます。
void Main()
{
var s = new MyStruct();
Test(s);
Debug.WriteLine(s.Description);
}
public void Test(IMyInterface i)
{
i.Description = "Test";
}
public interface IMyInterface
{
string Description { get; set; }
}
public struct MyStruct : IMyInterface
{
public string Description { get; set; }
}
これを実行すると、何が印刷されますか?
ヌル
では、なぜですか?
さて、問題は次の行です。
Test(s);
これは実際には、その構造体をボックス化し、ボックス化されたコピーをメソッドに渡します。そのボックス化されたコピーは正常に変更されていますが、s
何も割り当てられていない元の変数は変更されていないため、まだnull
.
では、コードの最初の部分を 1 行だけ変更すると、次のようになります。
IMyInterface s = new MyStruct();
これによって結果は変わりますか?
はい、ここでその構造体をボックス化し、ボックス化されたコピーを常に使用するためです。このコンテキストでは、オブジェクトのように動作します。ボックス化されたコピーを変更し、ボックス化されたコピーの内容を書き出します。
したがって、その構造体をボックス化またはボックス化解除するたびに問題が発生し、別々の生活を送るコピーが得られます。
結論: 可変構造体は悪です。
ここでの使用について 2 つの回答がref
ありましたが、これは間違ったツリーを吠えています。を使用するということは、追加する前にref
問題を解決したことを意味します。ref
これが例です。
上記のメソッドをパラメーターTest
を取るように変更すると、次のようになります。ref
public void Test(ref IMyInterface i)
これで何か変わるでしょうか?
いいえ、このコードは無効になっているためです:
var s = new MyStruct();
Test(ref s);
あなたはこれを得るでしょう:
「UserQuery.Test(ref UserQuery.IMyInterface)」に最適なオーバーロードされたメソッドの一致には、無効な引数がいくつかあります
引数 1: 'ref UserQuery.MyStruct' から 'ref UserQuery.IMyInterface' に変換できません
したがって、コードを次のように変更します。
IMyInterface s = new MyStruct();
Test(ref s);
しかし、ここで私の例に戻ってきました。追加しただけです。ref
これは、変更が反映されるために必要ではありません。
したがって、使用ref
は直交し、さまざまな問題を解決しますが、これは解決しません。
OK、 に関するその他のコメントref
。
はい、もちろん、構造体を使用して渡すref
と、実際に変更がプログラム全体に流れます。
それはこの質問の内容ではありません。質問はいくつかのコードを投稿し、それが機能するかどうかを尋ねました。この特定のコードのバリアントでは、機能します。でもつまずくのはとても簡単です。そして、質問が構造体とインターフェースに関するものであったことに特に注意してください。インターフェースを省略し、 を使用して構造体を渡すと、ref
何が得られるでしょうか? 別の質問です。
追加ref
しても、この質問も答えも変わりません。