64

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

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

我以前从未见过,也从未需要它。为什么有人想要这样做?Eric Lippert 提醒我们,一个功能必须有正当理由才能实施。什么伟大的用例可以证明这一点?有没有什么场景是无价的?我找不到任何关于它的文档1

此外,对于调用构造函数,已经有一种更广为人知的替代语法,所以这个特性有时是多余的:

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

我通过 C# 4th edition在 Jeffrey Richter 的 CLR 中的一个示例中找到了此功能。
1) 显然它在C# 规范中。

4

3 回答 3

54

好问题!

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

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

this像这样直接分配而不是分配给它的字段有点奇怪。更奇怪的是直接分配this然后覆盖该分配的 100%!

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

于 2013-02-08T08:51:10.783 回答
10

另外,我找不到任何关于它的文档。

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

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

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

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

至于它的用例,我不能立即想到很多 - 关于我唯一得到的就是如果你想在构造函数中分配的值计算起来很昂贵,并且你有一个缓存的值想复制进去this,可能比较方便。

于 2013-02-08T07:15:43.080 回答
0

包含该类型的公共和私有字段的存储位置聚合中的值类型的存储位置。将值类型传递给普通(值)参数将在物理上和语义上传递其所有字段的内容。将值类型作为ref参数传递在语义上是传递其所有字段的内容,尽管使用单个“byref”来传递所有字段。

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

由于这种行为,有些人称可变结构为“邪恶”,但唯一的邪恶是 C# 或 vb.net 都没有定义任何属性来指示结构成员或属性是否应该在不能调用的事物上调用直接通过ref

于 2013-02-10T01:28:51.367 回答