简体   繁体   English

C#中的自我分配

[英]Self assignment in C#

I was looking through some code I wrote a while ago and realized I made an assumption about the assignment operator in C#. 我正在查看我刚才写的一些代码,并意识到我在C#中对赋值运算符做了一个假设。 Here is the line of code in question (it works as expected): 这是有问题的代码行(它按预期工作):

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

pointsChecked is a List specified as a parameter to a recursive function. pointsChecked是一个List,指定为递归函数的参数。 It is a default parameter with default value null . 它是默认参数,默认值为null What I want to do is initialize it once and then build a collection of points that I have already checked, so it should only be initialized during the first iteration. 我想要做的是初始化一次然后构建我已经检查过的点集合,因此它应该只在第一次迭代期间初始化。

My assumption was that C# is guarded against self-assignment in the same way that C++ operator= should provide a guard when overloaded (ie, if(this == &rightHandSide) return *this; ). 我的假设是C#防止自我赋值,就像C ++ operator= 应该在重载时提供一个守卫一样(即if(this == &rightHandSide) return *this; )。 However, I haven't been able to find any resources that explicitly state that this is true for C#. 但是,我无法找到任何明确说明C#属实的资源。

The closest example I found was this question about the null-coalescing operator , where it appears that the object is assigned back to itself if it is not null . 我发现的最接近的例子是关于null-coalescing运算符的这个问题 ,如果该对象不为null ,则该对象似乎被分配回自身。 No one said anything about the self-assignment in that example, but I want to be certain that this isn't a bad practice and that there are no negative side effects. 在这个例子中,没有人说过自我指派的任何内容,但我想确定这不是一个坏的做法,并且没有负面的副作用。

Searching on MSDN I also found that (paraphrasing based on my understanding) the value on the right hand side is copied over to the value on the left hand side and returned. 在MSDN上搜索我也发现(根据我的理解释义)右侧的值被复制到左侧的值并返回。 So I am, again, unsure if it is a bad thing to do a self-assignment. 因此,我再次不确定自我指派是否是一件坏事。

I know I could do the following to be safer: 我知道我可以做到以下更安全:

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

But I would rather understand what is actually happening with self-assignment. 但我宁愿理解自我分配的实际情况。

Assignment copies the reference to an object, not the object contents. 赋值复制对象的引用,而不是对象内容。 No customizable code runs as part of an assignment to a variable holding an object reference, ever. 没有可自定义的代码作为对包含对象引用的变量的赋值的一部分运行。 This is also true for structs. 结构也是如此。

In C++ assignment is customizable, in C# it is not. 在C ++中,赋值是可自定义的,在C#中它不是。

It is safe to assign the same object reference to a variable already holding it: 将相同的对象引用分配给已经拥有它的变量是安全的:

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

This is as safe as assigning any other value: 这与分配任何其他值一样安全:

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

Note, that no general way exists to clone/copy an object. 请注意,克隆/复制对象没有通用的方法。 Any explanation relying on the presence of such a mechanism must be wrong. 任何依赖于这种机制存在的解释都必须是错误的。

Self-assignment is safe because it translates to the following approximate IL instructions: 自我指派是安全的,因为它转换为以下近似的IL指令:

ldloc someRef
stloc someRef

This has clearly defined semantics. 这明确定义了语义。 It first loads someRef onto the stack, then stores whatever is on the stack to someRef . 它首先将someRef加载到堆栈上,然后将堆栈中的任何内容存储到someRef

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM