248

我很好奇其他人如何使用this关键字。我倾向于在构造函数中使用它,但我也可以在整个类中的其他方法中使用它。一些例子:

在构造函数中:

public Light(Vector v)
{
    this.dir = new Vector(v);
}

别处

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}
4

31 回答 31

245

我并不是说这听起来很刺耳,但这没关系。

严重地。

看看重要的事情:你的项目、你的代码、你的工作、你的个人生活。他们中的任何一个都不会让他们的成功取决于您是否使用“this”关键字来限定对字段的访问。this 关键字不会帮助您按时发货。它不会减少错误,不会对代码质量或可维护性产生任何明显影响。它不会给你加薪,也不会让你在办公室花更少的时间。

这真的只是一个风格问题。如果您喜欢“这个”,请使用它。如果你不这样做,那就不要。如果您需要它来获得正确的语义,请使用它。事实是,每个程序员都有自己独特的编程风格。这种风格反映了特定程序员关于“最美观的代码”应该是什么样子的概念。根据定义,任何其他阅读您的代码的程序员都会有不同的编程风格。这意味着总会有你做的事情让其他人不喜欢,或者会做不同的事情。在某些时候,有些人会阅读您的代码并抱怨某事。

我不会为此烦恼。我只会根据您自己的口味确保代码尽可能美观。如果你问 10 位程序员如何格式化代码,你会得到大约 15 种不同的意见。更好的关注点是代码是如何分解的。事情抽象对了吗?我是否为事物选择了有意义的名称?有很多代码重复吗?有什么方法可以简化东西吗?我认为,把这些事情做好,将对你的项目、代码、工作和生活产生最大的积极影响。巧合的是,它可能也会让另一个人抱怨最少。如果您的代码有效、易于阅读并且经过充分考虑,那么其他人就不会仔细检查您如何初始化字段。他只是会使用你的代码,惊叹于它的伟大,

于 2008-08-22T20:42:19.137 回答
217

这个关键字在 C# 中有多种用法。

  1. 限定以相似名称隐藏的成员
  2. 让对象将自身作为参数传递给其他方法
  3. 让对象从方法中返回自身
  4. 声明索引器
  5. 声明扩展方法
  6. 在构造函数之间传递参数
  7. 在内部重新分配值类型(结构)值
  8. 在当前实例上调用扩展方法
  9. 将自己转换为另一种类型
  10. 链接在同一类中定义的构造函数

您可以通过在范围内没有同名的成员变量和局部变量来避免第一次使用,例如通过遵循常见的命名约定并使用属性(Pascal 大小写)而不是字段(驼峰大小写)来避免与局部变量(也是驼峰案子)。在 C# 3.0 中,可以使用自动实现的属性轻松地将字段转换为属性。

于 2008-08-22T21:12:48.937 回答
96

我只在绝对必要时使用它,即当另一个变量遮蔽另一个变量时。比如这里:

class Vector3
{
    float x;
    float y;
    float z;

    public Vector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

}

或者正如 Ryan Fox 指出的那样,当您需要将其作为参数传递时。(局部变量优先于成员变量)

于 2008-08-22T19:26:06.900 回答
54

就个人而言,我尝试在引用成员变量时始终使用它。它有助于澄清代码并使其更具可读性。即使没有歧义,第一次阅读我的代码的人也不知道这一点,但如果他们看到一致使用,他们就会知道他们是否正在查看成员变量。

于 2008-08-23T05:05:44.557 回答
38

我每次引用实例变量时都会使用它,即使我不需要。我认为它使代码更清晰。

于 2008-08-22T19:22:48.623 回答
36

我不敢相信所有说使用它总是“最佳实践”之类的人。

当有歧义时使用“this”,例如 Corey 的示例,或者当您需要将对象作为参数传递时,例如 Ryan 的示例。没有理由以其他方式使用它,因为能够基于作用域链解析变量应该足够清楚,因此不需要使用它来限定变量。

编辑:关于“this”的 C# 文档表明,除了我提到的两个之外,“this”关键字还有一种用途——用于声明索引器

编辑:@Juan:嗯,我的陈述中没有任何不一致之处 - 有 3 个实例我会使用“this”关键字(如 C# 文档中所述),而那些时候你确实需要它。当没有阴影发生时,在构造函数中的变量前面粘贴“this”只是浪费击键和阅读它时浪费我的时间,它没有任何好处。

于 2008-08-22T19:46:46.383 回答
27

每当StyleCop告诉我时,我都会使用它。必须遵守StyleCop 。哦是的。

于 2008-08-22T20:00:47.333 回答
11

任何时候您需要引用当前对象。

一个特别方便的场景是当您的对象正在调用一个函数并希望将自己传递给它时。

例子:

void onChange()
{
    screen.draw(this);
}
于 2008-08-22T19:26:37.430 回答
7

我也倾向于在任何地方使用它,只是为了确保我们正在处理的是实例成员。

于 2008-08-22T19:31:26.560 回答
5

我在任何可能有歧义的地方使用它(显然)。不仅是编译器歧义(在这种情况下需要),而且对于查看代码的人来说也是歧义。

于 2008-08-22T19:23:02.120 回答
5

this 关键字的另一个罕见用途是当您需要从实现类中调用显式接口实现时。这是一个人为的例子:

class Example : ICloneable
{
    private void CallClone()
    {
        object clone = ((ICloneable)this).Clone();
    }

    object ICloneable.Clone()
    {
        throw new NotImplementedException();
    }
}
于 2008-09-19T19:58:13.290 回答
4

这是我使用它的时候:

  • 从类中访问私有方法(以区分)
  • 将当前对象传递给另一个方法(或作为发送者对象,在事件的情况下)
  • 创建扩展方法时:D

我不将它用于私有字段,因为我在私有字段变量名称前加上下划线 (_)。

于 2008-08-22T21:19:47.533 回答
4

[C++]

我同意“当你必须”旅的时候使用它。不必要地装饰代码,不是一个好主意,因为当你忘记做到这一点时,编译器不会警告你。向人们展示了他们永远在那里的人来说潜在的混乱,即他们必须考虑它。

那么,你什么时候用它?我刚看看一些随机代码,发现这些例子(我没有对这些是好事或其他方式的判断):

  • 将“自己”传递给一个功能。
  • 将“自己”分配给指针或类似的东西。
  • 铸造,即上/下铸造(安全或其他),铸造康强等。
  • 编译器强制消除歧义。
于 2008-08-26T17:25:29.043 回答
3

您应该始终使用它,我用它来区分私有字段和参数(因为我们的命名约定规定我们不对成员和参数名称使用前缀(并且它们基于在 Internet 上找到的信息,所以我认为最佳实践))

于 2008-08-22T19:23:34.253 回答
3

在 Jakub Šturc 的回答中,他关于在构造函数之间传递数据的 #5 可能需要一点解释。this这是在重载构造函数中,并且是强制使用 of 的一种情况。在下面的示例中,我们可以使用默认参数从无参数构造函数中调用参数化构造函数。

class MyClass {
    private int _x
    public MyClass() : this(5) {}
    public MyClass(int v) { _x = v;}
}

我发现有时这是一个特别有用的功能。

于 2008-09-19T19:58:30.887 回答
3

我在接受对同一类型对象的引用的函数中使用它时,我想完全清楚我指的是哪个对象,在哪里。

例如

class AABB
{
  // ... members
  bool intersects( AABB other )
  {
    return other.left() < this->right() &&
           this->left() < other.right() &&

           // +y increases going down
           other.top() < this->bottom() &&
           this->top() < other.bottom() ;
  }
} ;

(对)

class AABB
{
  bool intersects( AABB other )
  {
    return other.left() < right() &&
           left() < other.right() &&

           // +y increases going down
           other.top() < bottom() &&
           top() < other.bottom() ;
  }
} ;

一目了然,AABBright()指的是哪个?这this增加了一点澄清剂。

于 2010-05-07T14:19:34.130 回答
2

我养成了在 Visual C++ 中大量使用它的习惯,因为这样做会触发 IntelliSense,我按了“>”键,而且我很懒。(并且容易出现拼写错误)

但我继续使用它,因为我发现我调用的是成员函数而不是全局函数很方便。

于 2008-08-26T02:00:07.817 回答
1

我倾向于用 _ 来强调字段,所以真的不需要使用它。无论如何,R# 也倾向于将它们重构掉......

于 2008-08-22T19:23:16.847 回答
1

我几乎只在从同一类型内部引用类型属性时使用它。正如另一位用户提到的,我还强调了本地字段,因此它们不需要this就很明显。

于 2008-08-22T19:29:51.620 回答
1

我只在需要时使用它,除了由于单参数多态性而必须放入一侧方法的对称操作:

boolean sameValue (SomeNum other) {
   return this.importantValue == other.importantValue;
} 
于 2008-09-06T11:50:15.717 回答
1

[C++]

在赋值运算符中使用,大多数情况下您必须检查和防止奇怪的(无意的、危险的或只是浪费程序时间)的事情,例如:

A a;
a = a;

您的赋值运算符将被写入:

A& A::operator=(const A& a) {
    if (this == &a) return *this;

    // we know both sides of the = operator are different, do something...

    return *this;
}
于 2008-09-16T07:25:18.530 回答
1

this在 C++ 编译器上

如果 C++ 编译器没有立即找到符号,它将默默地查找它。有时,大多数时候,它是好的:

  • 如果您没有在子类中重载它,则使用母类的方法。
  • 将一种类型的值提升为另一种类型

但有时,您只是不想让编译器猜测。您希望编译器选择正确的符号而不是另一个。

对我来说,那些时候是在一个方法中,我想访问一个成员方法或成员变量。我只是不想因为我写printf而不是print. this->printf不会编译。

关键是,对于 C 遗留库 (§)、多年前编写的遗留代码 (§§),或者在复制/粘贴已过时但仍处于活动状态的语言中可能发生的任何事情,有时会告诉编译器不要播放智慧是个好主意。

这些是我使用this.

(§) 这对我来说仍然是一种谜,但我现在想知道您是否在源代码中包含 <windows.h> 标头这一事实是否是所有遗留 C 库符号会污染您的全局命名空间的原因

(§§)意识到“你需要包含一个标题,但是包含这个标题会破坏你的代码,因为它使用了一些带有通用名称的愚蠢宏”是编码员生活中的俄罗斯轮盘赌时刻之一

于 2008-09-19T19:47:04.173 回答
1

'这。' 有助于在“this”类中找到具有大量成员的成员(通常是由于继承链较深)。

点击 CTRL+Space 对此没有帮助,因为它还包括类型;哪里——作为“这个”。仅包括会员。

我通常在拥有我所追求的东西后将其删除:但这只是我的风格突破。

在风格方面,如果你是一个独行侠——你自己决定;如果您为一家公司工作,请遵守公司政策(查看源代码控制中的内容,看看其他人在做什么)。在使用它来获得会员资格方面,既没有对也没有错。唯一错误的是不一致——这是风格的黄金法则。离开吹毛求疵的其他人。花时间思考真正的编码问题 - 显然是编码 - 相反。

于 2009-03-16T11:38:04.357 回答
1

我每次可以使用它。我相信它使代码更具可读性,更易读的代码等于更少的错误和更高的可维护性。

于 2009-04-23T18:54:08.083 回答
1

当您有许多开发人员使用相同的代码库时,您需要一些代码指南/规则。在我工作的地方,我们决定在字段、属性和事件上使用“this”。

对我来说,这样做很有意义,当您区分类变量和方法变量时,它使代码更容易阅读。

于 2009-04-23T20:12:37.223 回答
0

这取决于我正在使用的编码标准。如果我们使用 _ 来表示实例变量,那么“this”就变得多余了。如果我们不使用 _ 那么我倾向于使用它来表示实例变量。

于 2008-08-22T19:30:42.880 回答
0

我使用它来调用Intellisense,就像JohnMcG一样,但我会在完成后返回并擦除“this->”。我遵循 Microsoft 为成员变量添加前缀“m_”的约定,因此将其保留为文档将是多余的。

于 2008-09-19T20:09:16.663 回答
0

1 - 常见的 Java setter 习惯用法:

 public void setFoo(int foo) {
     this.foo = foo;
 }

2 - 以该对象为参数调用函数时

notifier.addListener(this);
于 2008-09-20T03:47:38.073 回答
0

在 C++ 中还没有提到一种用途,那就是不引用自己的对象或从接收的变量中消除成员的歧义。

您可以使用this在从其他模板继承的模板类中将非依赖名称转换为参数依赖名称。

template <typename T>
struct base {
   void f() {}
};

template <typename T>
struct derived : public base<T>
{
   void test() {
      //f(); // [1] error
      base<T>::f(); // quite verbose if there is more than one argument, but valid
      this->f(); // f is now an argument dependent symbol
   }
}

模板是使用两遍机制编译的。在第一轮中,仅解析和检查非参数依赖名称,而仅检查依赖名称的一致性,而不实际替换模板参数。

在这一步,在没有实际替换类型的情况下,编译器几乎没有关于base<T>可能是什么的信息(请注意,基本模板的特殊化可以将其变成完全不同的类型,甚至是未定义的类型),所以它只是假设它是一个类型. 在这个阶段,对程序员来说似乎很自然的非依赖调用f是一个符号,编译器必须找到它作为封闭命名空间的成员derived或封闭命名空间——这在示例中不会发生——它会抱怨。

解决方案是将非依赖名称f转换为依赖名称。这可以通过几种方式来完成,通过明确说明实现它的类型(base<T>::f--addingbase<T>使符号依赖,T编译器将假设它存在并推迟第二遍的实际检查,之后参数替换。

第二种方法,如果您从具有多个参数或长名称的模板继承,则更多排序器只是this->在符号前添加一个。由于您正在实现的模板类确实依赖于一个参数(它继承自base<T>this->是依赖于参数的,我们得到相同的结果:this->f在模板参数替换之后的第二轮检查。

于 2010-02-02T08:22:36.420 回答
-2

除非绝对必须,否则不应使用“this”。

有与不必要的冗长相关的惩罚。您应该争取与需要完全一样长的代码,而不再需要。

于 2008-09-02T16:42:19.263 回答
-8

绝不。曾经。如果您有变量阴影,那么您的命名约定就会出现问题。我的意思是,真的,成员变量没有区别命名?掌心

于 2008-08-22T19:53:31.173 回答