你什么时候使用“this”关键字?

时间:2008-08-22 19:21:25

标签: c# coding-style 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);
}

31 个答案:

答案 0 :(得分:239)

我并不是说这听起来很讽刺,但并不重要。

严重。

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

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

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

答案 1 :(得分:213)

C#中有this个关键字的几种用法。

  1. To qualify members hidden by similar name
  2. To have an object pass itself as a parameter to other methods
  3. 让对象从方法
  4. 返回
  5. To declare indexers
  6. To declare extension methods
  7. To pass parameters between constructors
  8. To internally reassign value type (struct) value
  9. 在当前实例上调用扩展方法
  10. 将自己投射到其他类型
  11. To chain constructors defined in the same class
  12. 您可以通过在作用域中不具有相同名称的成员和局部变量来避免第一次使用,例如通过遵循常见的命名约定并使用属性(Pascal大小写)而不是字段(camel case)来避免与局部变量发生冲突(也是骆驼案)。在C#3.0中,可以使用auto-implemented properties轻松地将字段转换为属性。

答案 2 :(得分:95)

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

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指出的那样,当你需要将此作为参数传递时。 (局部变量优先于成员变量)

答案 3 :(得分:50)

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

答案 4 :(得分:35)

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

答案 5 :(得分:35)

我无法相信所有使用它的人总是“最佳实践”等等。

当存在歧义时使用“this”,如Corey's example或需要将对象作为参数传递时,如Ryan's example中所示。没有理由使用它,否则因为能够根据范围链解析变量应该足够清楚,使用它的合格变量应该是不必要的。

编辑:关于“this”的C#文档表示除了我提到的两个之外,还有一个用于“this”关键字的用户 - for declaring indexers

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

答案 6 :(得分:27)

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

答案 7 :(得分:11)

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

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

示例:

void onChange()
{
    screen.draw(this);
}

答案 8 :(得分:6)

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

答案 9 :(得分:5)

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

答案 10 :(得分:5)

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

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

    object ICloneable.Clone()
    {
        throw new NotImplementedException();
    }
}

答案 11 :(得分:4)

这是我使用它的时候:

  • 从班级中访问私人方法(以区分)
  • 将当前对象传递给另一个方法(或发生事件时作为发件人对象)
  • 创建扩展方法时:D

我不将此用于私有字段,因为我使用下划线(_)为私有字段变量名称添加前缀。

答案 12 :(得分:4)

[C ++]

我同意“必须时使用它”旅。使用 this 不必要地装饰代码并不是一个好主意,因为编译器在您忘记执行此操作时不会发出警告。这给那些希望这个始终存在的人带来了潜在的混淆,即他们必须思考

那么,你什么时候使用它?我刚看了一些随机代码,发现了这些例子(我不会判断这些是好的要做的事情还是其他的):

  • 将“你自己”传递给一个功能。
  • 将“你自己”分配给指针或类似的东西。
  • 铸造,即上/下铸造(安全或其他),铸造常数等等。
  • 编译器强制消除歧义。

答案 13 :(得分: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() ;
  }
} ;

(VS)

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

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

AABB right()所指的是什么? this增加了一点澄清。

答案 14 :(得分:3)

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

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

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

答案 15 :(得分:2)

你应该总是使用它,我用它来区分私有字段和参数(因为我们的命名约定声明我们不使用成员和参数名称的前缀(并且它们基于互联网上的信息,所以我考虑这是一种最佳实践))

答案 16 :(得分:2)

我养成了在Visual C ++中自由使用它的习惯,因为这样做会触发我点击'&gt;'的智能感知钥匙,我很懒。 (并容易出现错别字)

但是我继续使用它,因为我觉得很容易看到我正在调用成员函数而不是全局函数。

答案 17 :(得分:1)

C ++编译器

this

如果符号没有立即找到,C ++编译器将静默查找符号。有时候,大部分时间都是好的:

  • 如果你没有在子类中重载它,则使用母类'方法。
  • 将类型的值提升为其他类型

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

对我来说,那些时间是在方法中我想要访问成员方法或成员变量的时间。我只是因为写了printf而不是print而不想要一些随机符号。 this->printf不会编译。

要点是,用C遗产库(§),遗留代码编写年前(§§),或任何可能发生的语言,其中的复制/粘贴是一个已经废弃,但仍然活跃的特征,有时,告诉编译器不玩智慧是一个好主意。

这些是我使用this的原因。

(§)它对我来说仍然是一种神秘,但我现在想知道你是否包含&lt; windows.h&gt;源代码中的标头是所有旧C库符号污染全局命名空间的原因

(§§)意识到,“你需要包括一个头,但包括这个头会破坏你的代码,因为它使用了一些愚蠢的宏具有通用名称”是其中的一个russian roulette编码器的时刻寿命

答案 18 :(得分:1)

'这个'。帮助在'this'类中找到成员很多(通常是由于深度继承链)。

点击CTRL + Space对此没有帮助,因为它还包括类型;在哪里 - 就像'这个'。仅包括会员。

我通常会删除它,一旦我拥有了我所追求的东西:但这只是我的风格突破。

就风格而言,如果你是一个独行侠 - 你决定;如果你为公司工作坚持公司政策(看看源代码管理中的东西,看看其他人在做什么)。在使用它来限定成员资格方面,无论是对还是错。唯一错误的是不一致 - 这是风格的黄金法则。留下挑选他人。花时间思考真正的编码问题 - 显然是编码 - 而不是。

答案 19 :(得分:1)

我倾向于使用_来强调字段,所以不需要使用它。 R#也倾向于重构它们......

答案 20 :(得分: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;
}

答案 21 :(得分:1)

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

boolean sameValue (SomeNum other) {
   return this.importantValue == other.importantValue;
} 

答案 22 :(得分:1)

在同一类型中引用类型属性时,我几乎只使用 this 。正如另一位用户所提到的,我也强调了本地字段,因此它们很明显,而不需要这个

答案 23 :(得分:0)

我使用它来调用 Intellisense ,就像JohnMcG一样,但我会回去删除“this-&gt;”当我完成了。我遵循Microsoft使用“m_”为成员变量添加前缀的约定,因此将其作为文档保留将是多余的。

答案 24 :(得分:0)

1 - Common Java setter idiom:

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

2 - 使用此对象作为参数调用函数时

notifier.addListener(this);

答案 25 :(得分:0)

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

答案 26 :(得分:0)

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

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

答案 27 :(得分: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 - 添加base<T>使符号依赖于T,编译器将只假设它会存在并在参数替换后推迟第二次传递的实际检查。

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

答案 28 :(得分:0)

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

答案 29 :(得分:-1)

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

与不必要的详细程度有关的罚款。你应该努力寻找完全符合需要的代码,而不再是代码。

答案 30 :(得分:-7)

从不。永远。如果你有变量阴影,你的命名约定就会破裂。我的意思是,真的,成员变量没有区别命名? 捂脸