2010-01-06 17 views
20

? Dado que las variables declaradas dentro de un método están disponibles solo dentro de ese método, y las variables declaradas privadas dentro de una clase solo están disponibles dentro de una clase. ¿Cuál es el propósito de la palabra clave this? ¿Por qué querría tener lo siguiente:¿Cuál es el propósito de esta palabra clave en C#

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

Cuando esto va a hacer exactamente lo mismo:

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

practicar mis habilidades de escritura?

+6

'this' palabra clave es la instancia de la clase, hará exactamente lo mismo. Las personas tal vez prefieran 'this.variablename' sobre 'variablename' para la legibilidad. –

+5

Nota pequeña: no creo que quiera devolver algo de un método marcado como 'void' ... –

+1

En una estructura,' this' se puede asignar a, lo cual es genial. Construiría una gran respuesta sobre esto, pero la pregunta es acerca de las clases. –

Respuesta

36

Hay un par de casos en los que es importante:

  • Si usted tiene un parámetro de función y una variable miembro con los mismos nombres, hay que ser capaces de distinguirlos:

    class Foo { 
        public Foo(int i) { this.i = i; } 
    
        private int i; 
    } 
    
  • Si realmente necesita referencia el objeto actual, en lugar de uno de sus miembros. Tal vez usted necesita para pasar a otra función:

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

    Por supuesto, lo mismo se aplica si desea retorno una referencia al objeto actual

+0

Vaya, mis ejemplos de código no tenían mucho sentido. Debería ser mejor ahora. – jalf

+5

Tercer lugar donde lo necesita: para encadenar a otro constructor en la misma clase. –

+2

Cuarto ejemplo: llamar a los métodos de extensión en usted mismo. –

28

En su ejemplo es puramente una cuestión de gustos, pero en este caso es un caso en el que no es:

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

Sin this, el código funcionaría de otra manera, la asignación del parámetro a sí mismo.

+6

Todavía es una cuestión de gusto. Algunos programadores nombran campos de instancia con un prefijo de subrayado y no necesitan usar 'this'. –

+8

Es una cuestión de gusto pero, como usted señala, tener una preferencia particular puede llevar a errores sutiles y difíciles de detectar. Mi preferencia es usar siempre 'this' para variables de ejemplo. – tvanfosson

+5

@Martinho Fernandes: excepto cuando comete un error y no sigue las pautas arbitrarias, entonces está realmente confundido. Es mucho mejor utilizar la función de idioma que un mecanismo de nomenclatura arbitrario para diferenciar la OMI. – tvanfosson

4

Necesita this si su parámetro de método tiene el mismo nombre que el campo.

private string variablename; 
private void SomeMethod(string variablename) 
{ 
    this.variablename = variablename+variablename; 
    return this.variablename; 
} 
3
  1. this significa su miembro actual instancia de clase no
    a. su miembro de la clase base
    b. miembro del alcance
    c. miembro estático
  2. Para que su código sea más legible.
3

Lo primero que me viene a la mente es la legibilidad y/o preferencia personal.

A veces, cuando estoy trabajando con una clase bastante grande ... o una clase con una clase base (donde no puedo "ver" algunas variables) ... Utilizo la palabra clave "this" ... como mínimo para intellisense en Visual Studio.

0

Es un problema de estilo principalmente. Si su método tiene un nombre de variable que es lo mismo que un miembro privado de la clase, usar esto ayuda a eliminar la ambigüedad. Esto podría evitar posibles errores tontos.

0

uso común es con argumentos de constructor que tienen el mismo nombre:

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

En la mayoría de los casos, utilizando this simplemente estorba el código. Sin embargo, lo he visto utilizado por otros programadores, presumiblemente para activar el intellisense para los miembros de la clase local.

La palabra clave this también es necesaria para usar en métodos de extensión.

public static class MyExtensions 
{ 
    public static int WordCount(this String str) 
    { 
     return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; 
    } 
} 
15

En muchos casos esto es útil. Aquí hay un ejemplo:

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

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

Aquí hay otro ejemplo. Supongamos que estoy escribiendo un Stream.Hacia fuera la forma que da salida a un objeto, y devuelve una referencia a la propia corriente, así:

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

Entonces, se podría utilizar esta salida de llamadas en un modo encadenado:

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

+1 - a menudo necesitas usar "esto" en un método donde quieras pasarte a otro objeto. –

+0

@Eric: Exactamente, buen resumen. Además, como en el segundo ejemplo que proporcioné arriba, cuando desea * regresar * usted mismo de un método. – Tarydon

4

En primer lugar, sus ejemplos son defectuosos porque ha marcado la clase como estática, por lo que no se puede crear una instancia.

De todos modos, this es simplemente una referencia a la instancia actual. Se puede utilizar para resolver los conflictos entre las variables locales y variables miembro, por ejemplo:

public class Foo 
{ 
    private string baz; 

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

También se puede utilizar simplemente como un objeto en sí mismo, por ejemplo:

public class Foo 
{ 
    public List<Foo> GetList(string baz) 
    { 
     var list = new List<Foo>(); 
     list.Add(this); 

     return list; 
    } 
} 

(No que este ejemplo es particularmente útil, pero se entiende la idea)

Editar:. Un ejemplo más realista es el modelo de eventos en .NET:

public class Foo 
{ 
    public EventHandler SomeEvent; 

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

nuevamente. . . gracias por criticar un ejemplo horrible que batí con bloc de notas. . . ;) – andrewWinn

3

Fuera de quizás Javascript, "esto" es principalmente una palabra clave de marcador de posición y lo más útil es hacer que su intento sea obvio al escribir un fragmento de código.

Básicamente, ayudará con la legibilidad.

2

respetuosamente en desacuerdo con algunos de los otros carteles. En C#, no es solo una cuestión de gusto; también está en línea con las pautas de estilo de C# de Microsoft (tanto interna como externamente, aunque no parecen cumplir sus propias directrices internamente).

hay ejemplos de casos en los que la notación que utilizó no funcionará:

private void DoSomething(object input) 
{ 
    input = input; 
} 

En su lugar, habría que utilizar la siguiente notación:

private void DoSomething(object input) 
{ 
    this.input = input; 
} 
+1

Hay una razón por la cual estas son pautas y no una regla de la ley que se castiga con la muerte. Hay muchas pautas que pueden no ser de uso. (Consulte el debate de las interfaces de etiquetado frente a los atributos meta) http://stackoverflow.com/questions/983037/are-tag-or-marker-interfaces-obsolete –

+0

Las pautas de estilo son una cuestión de gusto. –

+0

No estoy en desacuerdo con que las pautas de estilo sean subjetivas, pero lo que usted dice es equivalente a "Capitalizar los títulos de los libros es una cuestión de gusto". No es, de hecho, una cuestión de "gusto". Es una cuestión de estándares aceptados para el diseño de texto. –

3

En primer lugar, este es necesario cuando un método de clase necesita pasar una referencia al objeto a algún método en otra clase.

Por ejemplo:

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

A diferencia de algunos otros escenarios en los que usar o no usar "este". es una cuestión de estilo, o un medio para resolver una ambigüedad artificial.

2

this se refiere a la instancia de la clase, y en el ejemplo que nos muestra: utiliza this para referirse al campo llamado variablename.

Si tenía una variable local o un parámetro con el mismo nombre, necesitaría tener una forma de diferenciarlos. En ese caso, this se referirá al campo, mientras que el prefijo this se refiere a la variable o parámetro local.

Debe tener una convención de nomenclatura que lo ayude a diferenciar entre campos y locales. Esto lo salvará de los problemas que podrían ocurrir si posteriormente agrega un local con el mismo nombre a su método. (Desde código sin this entonces romper ...)

0

1) En primer lugar, y lo más importante, es una situación en la que un objeto tiene que pasar una referencia a sí mismo:

public class Element{ 
//... 
public Element Parent; 
public Element Root() 
{ 
if(Parent == null) 
    return this; 
return Parent.Root(); 
} 
} 
public void OnEvent() 
{ 
Event(this, new EventArgs()); 
} 

En interfaz fluida:

clase pública Query { public Query Add (Parámetro) {_list.Add (parameter); devuelve esto; }}

2) En segundo lugar, y método de extensión:

public class Extension 
{ 
public Element Root(this Element element) { 
    if(element.Parent == null) 
    return element; 
    return element.Parent.Root(); 
} 
} 

3) En tercer lugar, y realmente no lo necesita, para distinguir los parámetros de miembros de la clase. No lo necesita, porque una buena convención de codificación le ahorra el uso de la palabra clave 'this'.

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; 
} 
} 
5

Además de la "desambiguación campo" y "pasando una referencia de la isntance actual" respuestas (ya dada), hay un escenario adicional donde this es necesario; para llamar a los métodos de extensión en la instancia actual (estoy ignorando el uso de this en declarar un método de extensión, ya que no es exactamente el mismo significado que la pregunta):

class Foo 
{ 
    public void Bar() 
    { 
     this.ExtnMethod(); // fine 
     ExtnMethod(); // compile error 
    } 
} 
static class FooExt 
{ 
    public static void ExtnMethod(this Foo foo) {} 
} 

para ser justos, este no es un escenario común. Una más probable es simplemente para hacer más legible el código, por ejemplo:

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

en el anterior (o similar para Compare, Clone etc), sin la this. lo encuentro un poco ... "desequilibrada".

+0

"tuve" que usar esto cuando la clase base tenía métodos de extensión para proporcionar una interfaz más simple para algunas operaciones. –

+0

Y este es en realidad un caso especial del caso "pass a reference you yourself", excepto que es (sintaxis) recubierto de azúcar. –

0

Hay un principio que debe guiarlo para decidir si usar o no este '. ¿Necesitas referirte específicamente a ESTA instancia de la clase? Si lo haces, entonces usa 'esto'. De lo contrario, déjalo fuera.

El ejemplo de Logger otro póster proporcionado es un buen ejemplo de esto. No podía confiar en esto implícitamente, ya que necesitaba el objeto mismo.

No tiene sentido utilizar 'esto' como un prefijo para un método de la clase en sí, en la clase misma, ya que está implícito.

0

yo no puedo evitar ...

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

[KIDDDIIIING !!!]

0

Otro escenario Me'v ya se encuentran:

private int value; 
public int Value 
{ 
    get { return this.value; } 
    set { this.value = value; } //without this it doesn't make sense 
} 
+1

esto no funcionará, porque ha llamado al campo de respaldo '_value' y no' value'. – Oliver

+0

@Oliver, yap +1 para usted, arreglado por mí. – Dariusz

Cuestiones relacionadas