C#中的自我分配

时间:2013-09-15 18:10:28

标签: c# assignment-operator

我正在查看我刚才写的一些代码,并意识到我在C#中对赋值运算符做了一个假设。这是有问题的代码行(它按预期工作):

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

pointsChecked是指定为递归函数的参数的List。它是默认值,默认值为null。我想要做的是初始化一次,然后构建一个我已经检查过的点集合,所以它只应该在第一次迭代时初始化。

我的假设是C#在防止自我分配方面与C ++ operator= 在重载时提供防护(即if(this == &rightHandSide) return *this;)的方式相同。但是,我无法找到任何明确说明C#为真的资源。

我发现的最接近的示例是this question about the null-coalescing operator出现,如果对象不是null,则会将对象分配回自身。在这个例子中,没有人谈到自我任命的任何事情,但我想确定这不是一个不好的做法,并且没有负面的副作用。

Searching on MSDN我还发现(根据我的理解释义)右侧的值被复制到左侧的值并返回。所以我再次不确定自我分配是否是一件坏事。

我知道我可以做到以下更安全:

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

但我宁愿了解自我分配的实际情况。

1 个答案:

答案 0 :(得分:10)

分配复制对象的引用,而不是对象内容。没有可自定义的代码作为对包含对象引用的变量的赋值的一部分运行。结构也是如此。

在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