更改值类型的'this'变量

时间:2013-02-08 02:49:37

标签: c# this value-type

显然,您可以从结构中的任何位置更改this值(但不能在类中):

struct Point
{
    public Point(int x, int y)
    {
        this = new Point();
        X = x; Y = y;
    }
    int X; int Y;
}

我以前从未见过这种情况,也从未见过它。为什么一个人想要这样做? Eric Lippert reminds us必须证明某项功能是合理的。有什么好的用例可以证明这一点?有什么场景这是非常宝贵的吗? 我找不到任何文件 1

此外,对于调用构造函数,已经有一个更好的已知替代语法,因此此功能有时是多余的:

public Point(int x, int y)
    : this()
{
    X = x; Y = y;
}

我在Jeffrey Richter的CLR via C# 4th edition中找到了这个功能。
1)显然它位于C# specification

3 个答案:

答案 0 :(得分:54)

好问题!

根据定义,值类型按值复制。如果this实际上不是存储位置的别名,则构造函数将初始化副本,而不是初始化您要初始化的变量。这会使构造函数变得不那么有用!同样的方法;是的,可变结构是邪恶的,但如果你要再次创建一个可变结构,this必须是变异的变量,而不是它的值的副本。

您所描述的行为是该设计决策的逻辑结果:因为this别名变量,您可以分配给它,就像您可以分配给任何其他变量一样。

直接分配给this就好了,而不是分配给它的字段。直接分配给this然后覆盖100%的分配更奇怪!

避免使this成为接收者存储的别名的替代设计是从短期存储池中分配this,在ctor中初始化它,然后按值返回它。这种方法的缺点是它使得复制省略优化几乎不可能,并且它使得ctors和方法奇怪地不一致。

答案 1 :(得分:10)

  

另外,我找不到任何文件。

您是否尝试过查看C#规范?因为我可以找到它的文档(7.6.7):

  
      
  • 在结构的实例构造函数中的 primary-expression 中使用this时,它被归类为变量。变量的类型是发生用法的结构的实例类型(第10.3.1节),变量表示正在构造的结构。结构的实例构造函数的this变量与结构类型的out参数完全相同 - 特别是,这意味着必须在实例的每个执行路径中明确赋值变量构造

  •   
  • 在结构的实例方法或实例访问器中的 primary-expression 中使用this时,它被归类为变量。变量的类型是发生用法的结构的实例类型(第10.3.1节)。

         
        
    • 如果方法或访问器不是迭代器(第10.14节),则this变量表示调用方法或访问器的结构,其行为与ref的{​​{1}}参数完全相同。结构类型。
    •   
    • 如果方法或访问器是迭代器,则this变量表示调用方法或访问器的结构的副本,其行为与 value 参数完全相同结构类型。
    •   
  •   

至于它的一个用例,我不能立即想到很多 - 关于我唯一能得到的是你想在构造函数中分配的值计算成本高,而且你有一个要复制到this的缓存值,这可能很方便。

答案 2 :(得分:0)

包含该类型的公共和私有字段的存储位置聚合中的值类型的存储位置。传递值类型和普通(值)参数将在物理上和语义上传递其所有字段的内容。将值类型作为ref参数传递在语义上会传递其所有字段的内容,尽管只有一个" byref"用于传递所有这些。

在结构上调用方法等同于将结构(及其所有字段)作为ref参数传递,除了一个皱纹:通常,C#和vb.net都不允许只读要作为ref参数传递的值。但是,两者都允许在只读值或临时值上调用struct方法。他们通过复制所有结构(及其所有字段),然后将该副本作为ref参数传递来完成此操作。

由于这种行为,有些人会调用可变结构" evil",但唯一不好的事实是C#或vb.net都没有定义任何属性来指示是否有结构会员或财产应在ref无法直接传递的内容上发布。