13

少し前に書いたコードを調べていて、C# の代入演算子について仮定していたことに気付きました。問題のコード行は次のとおりです (期待どおりに動作します)。

pointsChecked = pointsChecked ?? new List<Point>();

pointsChecked再帰関数のパラメータとして指定されたリストです。これは、デフォルト値を持つデフォルト パラメータですnull。私がやりたいのは、一度初期化してから、すでにチェックしたポイントのコレクションを作成することです。そのため、最初の反復中にのみ初期化する必要があります。

operator= C# は、C++ がオーバーロードされたときにガードを提供するのと同じ方法で、自己代入に対してガードされていると想定していました(つまり、if(this == &rightHandSide) return *this;)。ただし、これが C# に当てはまることを明示的に述べているリソースを見つけることができませんでした。

私が見つけた最も近い例は、 null-coalescing operator に関するこの質問で、そうでない場合、オブジェクトがそれ自体に割り当てられているように見えますnull。この例の自己割り当てについては誰も何も言いませんでしたが、これは悪い習慣ではなく、負の副作用がないことを確認したいと思います。

MSDN で検索すると、(私の理解に基づいて言い換えると) 右側の値が左側の値にコピーされて返されることもわかりました。繰り返しになりますが、自己割り当てを行うことが悪いことなのかどうかはわかりません。

より安全にするために、次のことができることを知っています。

if(pointsChecked == null)
{
    pointsChecked = new List<Point>();
}

しかし、自己割り当てで実際に何が起こっているのかを理解したいと思います。

4

1 に答える 1

11

割り当ては、オブジェクトの内容ではなく、オブジェクトへの参照をコピーします。オブジェクト参照を保持する変数への割り当ての一部として、カスタマイズ可能なコードが実行されることはありません。これは構造体にも当てはまります。

C++ では代入はカスタマイズ可能ですが、C# ではそうではありません。

すでにそれを保持している変数に同じオブジェクト参照を割り当てても安全です。

object someRef = new object();
someRef = someRef; //always does nothing

これは、他の値を割り当てるのと同じくらい安全です。

int someVal = 123;
someVal = someVal; //always does nothing

オブジェクトをクローン/コピーする一般的な方法は存在しないことに注意してください。そのようなメカニズムの存在に依存する説明は間違っているに違いありません。

自己割り当ては、次のおおよその IL 命令に変換されるため安全です。

ldloc someRef
stloc someRef

これはセマンティクスを明確に定義しています。最初にスタックにロードsomeRefし、次にスタックにあるものを に格納しますsomeRef

于 2013-09-15T18:29:38.480 に答える