C#结构“this = ....”

时间:2012-03-10 18:16:03

标签: c# struct

我刚刚在反射器中浏览文件,并在结构构造函数中看到它:

this = new Binder.SyntaxNodeOrToken();

我之前没见过那个术语。有人可以解释这个赋值在C#中意味着什么。谷歌很难。

2 个答案:

答案 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)

如果s1s2Foo类型的结构,包含字段f1f2f3,则语句{{ 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 实例。然而,结构域的公开暴露不会造成任何此类危险。由于非平凡结构的可变实例的所有字段本质上都是可变的,不管结构可能允许变异的任何尝试,并且结构的不可变实例的所有字段都是不可变的,即使它们被暴露,结构也是如此努力使其领域“不可改变”的确是在说谎。谎言可能有时是有用的(例如,如果字段内容应该服从某些不变量),但是如果没有一些真正的原因则不应该告诉它。