我刚刚在反射器中浏览文件,并在结构构造函数中看到它:
this = new Binder.SyntaxNodeOrToken();
我之前没见过那个术语。有人可以解释这个赋值在C#中意味着什么。谷歌很难。
答案 0 :(得分:59)
它基本上取代了这个值。它有效地将所有字段从右侧复制到左侧......除非字段是只读的,否则它会起作用。是的, 看起来非常奇怪,而且有些可怕。
示例:
using System;
class Test
{
static void Main()
{
Point point = new Point(10, 20);
point.ReplaceWith(new Point(2, 3));
Console.WriteLine(point); // (2, 3)
}
}
struct Point
{
private readonly int x;
private readonly int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public void ReplaceWith(Point other)
{
this = other;
}
public override string ToString()
{
return string.Format("({0}, {1})", x, y);
}
}
有关更多信息,请阅读C#4规范的第7.6.7节,其中包括:
[关于在结构构造函数中使用的文本]
在结构的实例方法或实例访问器中的 primary-expression 中使用
this
时,它被归类为变量。变量的类型是发生使用的结构的实例类型。
如果方法或访问器不是迭代器,则
this
变量表示调用方法或访问器的结构,其行为与ref
的{{1}}参数完全相同。结构类型。[关于迭代器的文字]
答案 1 :(得分:5)
如果s1
和s2
是Foo
类型的结构,包含字段f1
,f2
和f3
,则语句{{ 1}}在语义上等同于
s1 = s2
除了不应该假设赋值操作的顺序(甚至是读写的相对顺序;例如,生成的代码可能将所有三个字段读入寄存器,然后写入所有三个字段) 。所有字段都将被复制,无论它们是公共的还是私有的,可变的或所谓的不可变的。将不会召唤任何财产获取者或制定者;源和目标结构都不会收到结构字段被复制或覆盖的任何通知。
语句s1.f1 = s2.f1;
s1.f2 = s2.f2;
s1.f3 = s2.f3;
在C#(*)中等同于
this = new Foo(whatever);
(*)vb.net中的struct构造函数语义是不同的
如上所述,字段分配不考虑字段是公共字段还是私有字段,而不考虑它们是否应该是不可变的。
我认为(与其他人的观点相反)结构应该经常暴露可变字段的一个原因是语法如下:
Foo temp;
call Foo's constructor (out temp, whatever);
this.f1 = temp.f1;
this.f2 = temp.f2;
this.f3 = temp.f3;
使// Assume myKVP is a field of type KeyValuePair<Wizzle, int>
rr = new KeyValuePair<Wizzle, int>(myKVP.Key, myKVP.Value + 1);
看起来好像是从之前的内容分配后引用不同的实例,当实际发生的是:
myKVP
换句话说,该语句不会使// Assumes backing fields are named _Key and _Value
// Note that C# won't allow one to write private fields directly, but the
// act of copying one struct instance to another copies all the fields,
// public and private, from the source instance to the destination.
KeyValuePair<Wizzle, int> temp;
temp._Key = myKVP.Key; // Constructor has access to backing fields
temp._Value = myKVP.Value+1;
myKVP._Key = temp._Key; // Struct assignment copies all fields, public and private
myKVP.Value = temp.Value;
向另一个实例报告;相反,它创建一个新实例,通过用新实例的字段覆盖其字段来改变旧实例,然后丢弃新实例。如果某些代码在进行上述分配时正在评估myKVP
,则该变异会影响正在打印的myKVP.ToString()
实例。
结构可以有有用的语义,但所谓的“不可变”结构不是。当且仅当它们被保存在可变的存储位置中时,非平凡的结构(可以创建与默认值不同的值)是可变的,而不管该类型强加的任何语义。自变异结构,即在构造函数和属性设置器之外的任何方法中变异myMVP
的结构,可能会有一些意想不到的行为,因为编译器无法禁止调用其他方法,这些方法会使this
变异。不可变的struct 实例。然而,结构域的公开暴露不会造成任何此类危险。由于非平凡结构的可变实例的所有字段本质上都是可变的,不管结构可能允许变异的任何尝试,并且结构的不可变实例的所有字段都是不可变的,即使它们被暴露,结构也是如此努力使其领域“不可改变”的确是在说谎。谎言可能有时是有用的(例如,如果字段内容应该服从某些不变量),但是如果没有一些真正的原因则不应该告诉它。