C#中的自我分配

E. *_*fat 12 c# assignment-operator

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

pointsChecked = pointsChecked ?? new List<Point>();
Run Code Online (Sandbox Code Playgroud)

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

我的假设是C#可以防止自我分配,就像C++ 在过载时operator= 应该提供一个后卫一样(即if(this == &rightHandSide) return *this;).但是,我无法找到任何明确说明C#属实的资源.

我发现的最接近的例子是关于null-coalescing运算符的这个问题,如果不是,那么它似乎会将对象分配回自身null.在这个例子中,没有人说过自我指派的任何内容,但我想确定这不是一个坏的做法,并且没有负面的副作用.

在MSDN上搜索我也发现(根据我的理解释义)右侧的值被复制到左侧的值并返回.因此,我再次不确定自我指派是否是一件坏事.

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

if(pointsChecked == null)
{
    pointsChecked = new List<Point>();
}
Run Code Online (Sandbox Code Playgroud)

但我宁愿理解自我分配的实际情况.

usr*_*usr 10

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

在C++中,赋值是可自定义的,在C#中它不是.

将相同的对象引用分配给已经拥有它的变量是安全的:

object someRef = new object();
someRef = someRef; //always does nothing
Run Code Online (Sandbox Code Playgroud)

这与分配任何其他值一样安全:

int someVal = 123;
someVal = someVal; //always does nothing
Run Code Online (Sandbox Code Playgroud)

请注意,克隆/复制对象没有通用的方法.任何依赖于这种机制存在的解释都必须是错误的.

自我指派是安全的,因为它转换为以下近似的IL指令:

ldloc someRef
stloc someRef
Run Code Online (Sandbox Code Playgroud)

这明确定义了语义.它首先加载someRef到堆栈上,然后存储堆栈中的任何内容someRef.

  • 赋值运算符不能重载.对于ref类型和结构都没有.结构副本是指定的IL指令,它指示运行时执行按位复制. (2认同)