C#中'this'关键字的目的是什么?

20

由于在方法内声明的变量仅在该方法内可用,而在类内声明为私有的变量仅在该类内可用。那么this关键字的目的是什么?为什么我想要以下内容:

private static class SomeClass : ISomeClass
{
    private string variablename;
    private void SomeMethod(string toConcat)
    {
        this.variablename = toConcat+toConcat;
        return this.variablename;
    }
}

当这样做完全相同的事情时:

private static class SomeClass : ISomeClass
{
    private string variablename;
    private void SomeMethod(string toConcat)
    {
        variablename = toConcat+toConcat;
        return variablename;
    }
}

练习我的打字技能吗?


6
this关键字指的是类的实例,它会执行完全相同的操作。人们可能更喜欢使用this.variablename来代替variablename以提高可读性。 - Anthony Forloney
5
小提示:我认为您不想从标记为void的方法中返回任何内容... - Sarah Vessels
1
在一个结构体中,this 实际上是可以被赋值的,这非常酷。我本来想围绕这个建立一个大型答案,但问题是关于类的。 - Jeffrey L Whitledge
你也不能在一个“静态”类中拥有实例级别的方法,我也不认为一个静态类可以继承另一个类... - Kurru
2
好的……所以我感激人们对我所举的糟糕例子的批评……;) - andrewWinn
@Kurru 正确。静态类必须直接继承自 System.Object。它实际上只继承了 Object 中的两个 static 方法。在这个问题中,ISomeClass 要么是一个接口(而静态类无法实现接口!),要么是一个与 System.Object 不同的类。 - Jeppe Stig Nielsen
19个回答

36

有几种情况下需要注意:

  • 如果您有一个函数参数和一个同名的成员变量,您需要能够区分它们:

class Foo {
  public Foo(int i) { this.i = i; }

  private int i;
}
如果您实际上需要引用“当前对象”,而不是其中的成员,则可能需要将其传递给另一个函数:
class Foo {
  public static DoSomething(Bar b) {...}
}

class Bar {
  public Bar() { Foo.DoSomething(this); }
}

当然,如果你想要返回当前对象的引用,同样也适用。


5
第三种需要使用的情况是:在同一个类中将当前构造函数链接到另一个构造函数。 - Jon Skeet
2
第四个例子:调用自身的扩展方法。 - R. Martinho Fernandes
3
@Jon:没错,虽然我认为这是一个特殊情况。在那种情况下,他们本可以使用一个独特的关键词,因为它并不仅仅是作为当前对象的引用。它具有特殊的语义。 - jalf
1
方法参数与成员变量同名的情况似乎是设计不良。 - Sarah Vessels
2
@Sarah:以Person类为例。如果构造函数的参数是“name”,而这个参数恰好对应了类中的一个字段,那么为什么要给它取一个不同的名字呢?毕竟它就是“name”啊。 - R. Martinho Fernandes
显示剩余3条评论

28

在你的例子中,这只是一件关于口味的事情,但这里有一个不同的例子:

private string SomeMethod(string variablename)
{
    this.variablename = variablename;
    return this.variablename;
}

没有 this,代码将以不同的方式运行,将参数分配给自身。


6
这仍然是一个品味问题。一些程序员用下划线前缀命名实例字段并且不需要使用 this - R. Martinho Fernandes
8
这是一个品味问题,但正如你所指出的,有特定的偏好可能会导致难以检测到的微妙错误。我的偏好是始终针对实例变量使用this - tvanfosson
5
除非你犯了错误并且没有遵循任意的指南,否则你会感到困惑。在我看来,更好的做法是使用语言特性而不是任意的命名机制来区分它们。 - tvanfosson
1
@tvanfosson:同意,但不幸的是我无法说服那些坚持使用下划线前缀的人... 这又是一场圣战。 - R. Martinho Fernandes
1
只要保持一致,任何方式都无所谓。由于编译器无论如何都不会告诉你哪个正确,它们在这个特定的上下文中都是有效的约定。就我个人而言,我使用下划线,而在C#社区中似乎非常普遍。相比之下,“this.”让我感到不舒服,但我很容易“忽略”下划线却仍能注意到它的存在。正如他们所说,“因材施教”(根据不同情况采用不同方法)... - Neil Hewitt
显示剩余8条评论

15

有许多情况下这非常有用。以下是一个例子:

class Logger { 
   static public void OutputLog (object someObj) {
      ...
   }
}

class SomeClass { 
   private void SomeMethod () { 
      Logger.OutputLog (this);
   } 
}

这里有另外一个例子。假设我正在编写一个Stream.Out方法,它输出一个对象,并返回对流本身的引用,就像这样:

class Stream {
   public Stream Out (object obj) { 
      ... code to output obj ...
      return this; 
   }
}

然后,可以将此Out调用链式使用:

Stream S = new Stream (...);
S.Out (A). Out (B). Out (C);

1
+1 - 在某些方法中,如果你想将自己传递给其他对象,你经常需要使用 "this"。 - Eric Petroelje
@Eric:完全正确,总结得很好。另外,就像我上面提供的第二个例子一样,当你想要从一个方法中 返回 时。 - Tarydon

5
除了已经给出的“字段消歧义”和“传递当前实例的引用”答案之外,还有一种情况需要使用this关键字;即在当前实例上调用扩展方法(我忽略了在声明扩展方法中使用this的用法,因为那与问题的意思不完全相同)。
class Foo
{
    public void Bar()
    {
        this.ExtnMethod(); // fine
        ExtnMethod(); // compile error
    }
}
static class FooExt
{
    public static void ExtnMethod(this Foo foo) {}
}

公平地说,这不是一个常见的情况。更可能的情况是为了使代码更易读,例如:

public bool Equals(Foo other) {
    return other != null && this.X == other.X && this.Y == other.Y;
}

在上面的代码中(或类似于CompareClone等),如果没有this.,我会感到有点...“不平衡”。

当基类具有扩展方法以为某些操作提供更简单的接口时,我“不得不”使用这个。 - R. Martinho Fernandes
这实际上是“传递对自身的引用”情况的一个特例,只不过它被(语法)糖包围了。 - R. Martinho Fernandes

4

如果您的方法参数与字段名称相同,则需要this

private string variablename;
private void SomeMethod(string variablename)
{
    this.variablename = variablename+variablename;
    return this.variablename;
}

4
在大多数情况下,使用this只会使代码变得混乱。然而,我看到其他程序员使用它,可能是为了触发本地类成员的智能感知。 this关键字也必须用于扩展方法中。
public static class MyExtensions
{
    public static int WordCount(this String str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
}  

4
首先,您的示例存在缺陷,因为您将类标记为静态,因此无法实例化。
无论如何,“this”只是对当前实例的引用。它可以用于解决局部变量和成员变量之间的冲突,例如:
public class Foo
{
    private string baz;

    public void Bar(string baz)
    {
        this.baz = baz;
    }
}

它也可以作为一个独立的对象使用,例如:
public class Foo
{
    public List<Foo> GetList(string baz)
    {
        var list = new List<Foo>();
        list.Add(this);

        return list;
    }
}

(请注意,这个例子并不是特别有用,但你能够理解意思。)

编辑:一个更现实的例子是.NET中的事件模型:

public class Foo
{
    public EventHandler SomeEvent;

    public void Bar()
    {
        if (SomeEvent != null)
        {
            SomeEvent(this, EventArgs.Empty);
        }
    }
}

再次感谢您对我用记事本编写的糟糕示例进行批评。;) - andrewWinn

3

首先,当一个类方法需要将对象的引用传递给另一个类中的某个方法时,是必要的。

例如:

class Image
{
    void Refresh()
    {
        Screen.DrawImage(this);
    }
}

与其他一些情况不同,使用或不使用 "this." 并不是样式问题,也不是解决人为歧义的手段。


3
  1. this代表当前类实例成员,而不是
    a. 基类成员
    b. 作用域成员
    c. 静态成员
  2. 为了让你的代码更易读。

3

除了JavaScript外,“this”大多数情况下是一个占位符关键字,它最有用的地方是在编写代码时使您的意图明显。

基本上,它将有助于提高可读性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接