C#中’this’关键字的用途是什么


What is the purpose of 'this' keyword in C#

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

1
2
3
4
5
6
7
8
9
private static class SomeClass : ISomeClass
{
    private string variablename;
    private void SomeMethod(string toConcat)
    {
        this.variablename = toConcat+toConcat;
        return this.variablename;
    }
}

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

1
2
3
4
5
6
7
8
9
private static class SomeClass : ISomeClass
{
    private string variablename;
    private void SomeMethod(string toConcat)
    {
        variablename = toConcat+toConcat;
        return variablename;
    }
}

练习打字技巧?


有几个情况很重要:

  • 如果函数参数和成员变量具有相同的名称,则需要能够区分它们:

    1
    2
    3
    4
    5
    class Foo {
      public Foo(int i) { this.i = i; }

      private int i;
    }
  • 如果实际需要引用当前对象,而不是其成员之一。也许您需要将它传递给另一个函数:

    1
    2
    3
    4
    5
    6
    7
    class Foo {
      public static DoSomething(Bar b) {...}
    }

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

    当然,如果您想返回对当前对象的引用,同样适用


在您的示例中,这纯粹是一个品味问题,但这里的情况并非如此:

1
2
3
4
5
private string SomeMethod(string variablename)
{
    this.variablename = variablename;
    return this.variablename;
}

如果没有this,代码将以不同的方式工作,将参数分配给自己。


在许多情况下,这是有用的。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
class Logger {
   static public void OutputLog (object someObj) {
      ...
   }
}

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

这是另一个例子。假设我正在编写一个stream.out方法,该方法输出一个对象,并返回对流本身的引用,如下所示:

1
2
3
4
5
6
class Stream {
   public Stream Out (object obj) {
      ... code to output obj ...
      return this;
   }
}

然后,可以在链接模式下使用这个out调用:

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


除了"字段消歧"和"传递当前istance的引用"答案(已经给出)之外,还有一个附加的场景,其中this是必需的;在当前实例上调用扩展方法(我在声明扩展方法时忽略了this的用法,因为这与他问:

1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
    public void Bar()
    {
        this.ExtnMethod(); // fine
        ExtnMethod(); // compile error
    }
}
static class FooExt
{
    public static void ExtnMethod(this Foo foo) {}
}

公平地说,这不是常见的情况。更可能的方法是简单地提高代码的可读性,例如:

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

在上面(或类似于CompareClone等),没有this.我觉得有点……""不平衡"。


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

1
2
3
4
5
6
private string variablename;
private void SomeMethod(string variablename)
{
    this.variablename = variablename+variablename;
    return this.variablename;
}

在大多数情况下,使用this只会使代码混乱。不过,我见过其他程序员使用它,可能是为了触发本地类成员的IntelliSense。

扩展方法中也需要使用this关键字。

1
2
3
4
5
6
7
public static class MyExtensions
{
    public static int WordCount(this String str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
}


首先,您的示例是有缺陷的,因为您已经将类标记为静态的,所以它不能被实例化。

无论如何,this只是对当前实例的引用。它可以用来解决局部变量和成员变量之间的冲突,例如:

1
2
3
4
5
6
7
8
9
public class Foo
{
    private string baz;

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

它也可以简单地作为一个对象来使用,例如:

1
2
3
4
5
6
7
8
9
10
public class Foo
{
    public List<Foo> GetList(string baz)
    {
        var list = new List<Foo>();
        list.Add(this);

        return list;
    }
}

(不是说这个例子特别有用,但你明白了。)

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

1
2
3
4
5
6
7
8
9
10
11
12
public class Foo
{
    public EventHandler SomeEvent;

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


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

例如:

1
2
3
4
5
6
7
class Image
{
    void Refresh()
    {
        Screen.DrawImage(this);
    }
}

与其他一些使用或不使用"this"的场景不同,它是一种风格问题,或解决人为模糊性的方法。


我首先想到的是可读性和/或个人偏好。

有时当我在一个相当大的班级工作时…或者一个带有基类的类(在这里我看不到一些变量)。我用这个关键词…至少对于Visual Studio中的IntelliSense。


  • this表示当前类实例成员不
    a.您的基类成员
    b.范围成员
    c.静态构件
  • 使代码更可读。

  • 除了可能的javascript之外,"this"主要是一个占位符关键字,最有用的是在编写一段代码时使您的意图变得明显。

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


    我尊重地不同意其他一些海报。在C中,这不仅仅是一个品味问题,它还符合微软的C风格指导原则(内部和外部,尽管他们似乎不符合自己的指导原则)。

    例如,当您使用的符号不起作用时:

    1
    2
    3
    4
    private void DoSomething(object input)
    {
        input = input;
    }

    相反,您需要使用以下符号:

    1
    2
    3
    4
    private void DoSomething(object input)
    {
        this.input = input;
    }


    this指的是类的实例,在这个例子中,您向我们展示了:您使用this指的是名为variablename的字段。

    如果您有一个同名的局部变量或参数,那么您需要有一种区分它们的方法。在这种情况下,this指的是字段,而不加前缀的this指的是局部变量或参数。

    您应该有一个命名约定来帮助您区分字段和本地变量。如果您以后向方法中添加具有相同名称的本地变量,这将使您免受可能发生的问题的影响。(因为没有this的代码会中断…)


    我已经找到另一个场景:

    1
    2
    3
    4
    5
    6
    private int value;
    public int Value
    {
        get { return this.value; }
        set { this.value = value; } //without this it doesn't make sense
    }


    1)首先,也是最重要的,是当一个对象需要传递一个对其自身的引用时:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Element{
    //...
    public Element Parent;
    public Element Root()
    {
     if( Parent == null )
      return this;
     return Parent.Root();
    }
    }
    public void OnEvent()
    {
     Event(this, new EventArgs());
    }

    在Fluent界面中:

    公共类查询{公共查询添加(参数参数)列表.添加(参数);返回此;}

    2)二次进展法:

    1
    2
    3
    4
    5
    6
    7
    8
    public class Extension
    {
     public Element Root(this Element element) {
      if( element.Parent == null )
       return element;
      return element.Parent.Root();
     }
    }

    3)第三,你真的不需要它来区分参数和类成员。您不需要它,因为良好的编码约定可以避免使用"this"关键字。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class Element
    {
     public Element Parent;
     publlc void SetParent(Element parent)
     {
       // this.Parent = parent; // see, you don't need it
       Parent = parent;
     }
    }
    //...
    public class Element
    {
     public Element _parent;
     public Element Parent { get { return _parent; } }
     publlc void SetParent(Element parent)
     {
       // this._parent = parent; // see, you don't need it
       _parent = parent;
     }
    }

    有一个原则可以指导您决定是否使用"this"。您需要具体地引用这个类的实例吗?如果你这样做了,那就用"这个"。否则,把它放在一边。

    记录器示例提供的另一个海报就是一个很好的例子。因为他需要物体本身,所以他不能依赖于一个隐含的事实。

    在类本身中,使用"this"作为类本身的方法的前缀是没有意义的,因为它是隐式的。


    常用于具有相同名称的构造函数参数:

    1
    2
    3
    4
    public SomeClass(string variablename)
    {
       this.variablename = variablename;
    }

    它主要是一个风格问题。如果您的方法有一个与私有类成员相同的变量名,那么使用它有助于消除歧义。这可能会防止愚蠢的错误。


    我忍不住…

    1
    2
    if (this == null)
        throw new NullReferenceException();

    [孩子们!!!!]