Pregunta

Tenía curiosidad sobre cómo otras personas usan el este palabra clave.Tiendo a usarlo en constructores, pero también puedo usarlo en toda la clase en otros métodos.Algunos ejemplos:

En un constructor:

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

En otra parte

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}
¿Fue útil?

Solución

Hay varios usos de este palabra clave en C#.

  1. Para calificar a miembros ocultos por nombre similar
  2. Para que un objeto se pase a sí mismo como parámetro a otros métodos
  3. Para que un objeto regrese a sí mismo desde un método
  4. Para declarar indexadores
  5. Para declarar métodos de extensión
  6. Para pasar parámetros entre constructores
  7. Para reasignar internamente el valor del tipo de valor (estructura).
  8. Para invocar un método de extensión en la instancia actual
  9. Lanzarse a otro tipo
  10. Para encadenar constructores definidos en la misma clase

Puede evitar el primer uso al no tener variables miembro y locales con el mismo nombre en el alcance, por ejemplo, siguiendo convenciones de nomenclatura comunes y usando propiedades (caso Pascal) en lugar de campos (caso camello) para evitar colisionar con variables locales (también camello). caso).En C# 3.0, los campos se pueden convertir en propiedades fácilmente utilizando propiedades implementadas automáticamente.

Otros consejos

No quiero que esto suene sarcástico, pero no importa.

En serio.

Mira las cosas que son importantes:tu proyecto, tu código, tu trabajo, tu vida personal.El éxito de ninguno de ellos dependerá de si utiliza o no la palabra clave "esta" para calificar el acceso a los campos.Esta palabra clave no le ayudará a realizar el envío a tiempo.No reducirá los errores, no tendrá ningún efecto apreciable en la calidad o la capacidad de mantenimiento del código.No le dará un aumento ni le permitirá pasar menos tiempo en la oficina.

En realidad es sólo una cuestión de estilo.Si te gusta "esto", úsalo.Si no lo haces, entonces no lo hagas.Si lo necesita para obtener la semántica correcta, úselo.La verdad es que cada programador tiene su propio estilo de programación único.Ese estilo refleja las nociones de ese programador en particular sobre cómo debería verse el "código más agradable desde el punto de vista estético".Por definición, cualquier otro programador que lea su código tendrá un estilo de programación diferente.Eso significa que siempre habrá algo que hiciste que al otro no le guste o que hubiera hecho de otra manera.En algún momento, algún tipo leerá tu código y se quejará de algo.

No me preocuparía por eso.Solo me aseguraría de que el código sea lo más agradable posible desde el punto de vista estético según sus propios gustos.Si preguntas a 10 programadores cómo formatear el código, obtendrás unas 15 opiniones diferentes.Es mejor centrarse en cómo se factoriza el código.¿Están bien las cosas abstractas?¿Elegí nombres significativos para las cosas?¿Hay mucha duplicación de código?¿Hay formas de simplificar las cosas?Creo que hacer esas cosas bien tendrá el mayor impacto positivo en su proyecto, su código, su trabajo y su vida.Casualmente, probablemente también hará que el otro tipo sea el que menos se queje.Si su código funciona, es fácil de leer y está bien factorizado, el otro tipo no examinará cómo inicializa los campos.Simplemente usará su código, se maravillará de su grandeza y luego pasará a otra cosa.

Sólo lo uso cuando es absolutamente necesario, es decir, cuando otra variable sigue a otra.Como aquí:

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

}

O como señala Ryan Fox, cuando necesitas pasar esto como parámetro.(Las variables locales tienen prioridad sobre las variables miembro)

Personalmente, trato de usar siempre este cuando se hace referencia a variables miembro.Ayuda a aclarar el código y hacerlo más legible.Incluso si no hay ambigüedad, alguien que lea mi código por primera vez no lo sabe, pero si ve este Si se usa de manera consistente, sabrán si están mirando una variable miembro o no.

Lo uso cada vez que hago referencia a una variable de instancia, incluso si no es necesario.Creo que hace que el código sea más claro.

No puedo creer que todas las personas que dicen que usarlo siempre sea una "mejor práctica" y cosas así.

Utilice "esto" cuando haya ambigüedad, como en El ejemplo de Corey o cuando necesita pasar el objeto como parámetro, como en El ejemplo de Ryan.No hay razón para usarlo de otra manera porque poder resolver una variable basada en la cadena de alcance debería ser lo suficientemente claro como para que calificar variables con ella sea innecesario.

EDITAR:La documentación de C# sobre "this" indica un uso más, además de los dos que mencioné, para la palabra clave "this": para declarar indexadores

EDITAR:@Juan:Eh, no veo ninguna inconsistencia en mis declaraciones: hay 3 casos en los que usaría la palabra clave "this" (como se documenta en la documentación de C#), y esos son momentos en los que realmente necesidad él.Poner "esto" delante de las variables en un constructor cuando no hay sombreado es simplemente una pérdida de pulsaciones de teclas y una pérdida de tiempo al leerlo, no proporciona ningún beneficio.

lo uso siempre EstiloCop me dice que lo haga. EstiloCop debe ser obedecido.Oh sí.

Cada vez que necesite una referencia al objeto actual.

Un escenario particularmente útil es cuando su objeto llama a una función y quiere pasar a ella.

Ejemplo:

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

También tiendo a usarlo en todas partes, solo para asegurarme de que quede claro que estamos tratando con miembros de la instancia.

Lo uso en cualquier lugar donde pueda haber ambigüedad (obviamente).No solo la ambigüedad del compilador (sería necesario en ese caso), sino también la ambigüedad para alguien que mira el código.

Otro uso algo raro de la palabra clave this es cuando necesita invocar una implementación de interfaz explícita desde dentro de la clase de implementación.He aquí un ejemplo artificial:

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

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

Aquí es cuando lo uso:

  • Accediendo a métodos privados desde dentro de la clase (para diferenciar)
  • Pasar el objeto actual a otro método (o como objeto remitente, en caso de un evento)
  • Al crear métodos de extensión :D

No uso esto para campos privados porque prefijo los nombres de variables de campos privados con un guión bajo (_).

[C++]

Estoy de acuerdo con la brigada "úsalo cuando sea necesario".Decorar código innecesariamente con este no es una gran idea porque el compilador no le avisará cuando olvide hacerlo.Esto introduce una posible confusión para las personas que esperan este estar siempre ahí, es decirtendrán que pensar al respecto.

Entonces, ¿cuándo lo usarías?Acabo de echar un vistazo a un código aleatorio y encontré estos ejemplos (no estoy juzgando si son bien cosas que hacer o no):

  • Pasando "usted mismo" a una función.
  • Asignar "usted mismo" a un puntero o algo así.
  • Fundición, es decirlanzamiento hacia arriba/abajo (seguro o no), desechar la constancia, etc.
  • El compilador impuso la desambiguación.

Lo uso cuando, en una función que acepta una referencia a un objeto del mismo tipo, quiero que sea perfectamente claro a qué objeto me refiero, dónde.

Por ejemplo

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() ;
  }
} ;

(contra)

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

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

De un vistazo lo que hace la AABB right() ¿Referirse a?El this agrega un poco de clarificador.

En la respuesta de Jakub Šturc, su número 5 sobre pasar datos entre constructores probablemente necesitaría una pequeña explicación.Esto ocurre al sobrecargar constructores y es el único caso en el que el uso de this es obligatorio.En el siguiente ejemplo podemos llamar al constructor parametrizado desde el constructor sin parámetros con un parámetro predeterminado.

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

En ocasiones, he descubierto que esta es una característica particularmente útil.

Siempre debes usarlo, yo lo uso para diferenciar campos y parámetros privados (porque nuestras convenciones de nomenclatura establecen que no usamos prefijos para los nombres de miembros y parámetros (y se basan en información que se encuentra en Internet, por lo que considero que es un mejores prácticas))

Adquirí el hábito de usarlo generosamente en Visual C++ ya que al hacerlo se activarían los de IntelliSense. Presioné la tecla '>' y soy vago.(y propenso a errores tipográficos)

Pero seguí usándolo, ya que me resulta útil ver que estoy llamando a una función miembro en lugar de a una función global.

Tiendo a subrayar los campos con _, así que nunca necesito usar esto.Además, R# tiende a refactorizarlos de todos modos...

Prácticamente solo uso este al hacer referencia a una propiedad de tipo desde dentro del mismo tipo.Como mencionó otro usuario, también subrayo los campos locales para que se noten sin necesidad este.

Lo uso sólo cuando es necesario, excepto para operaciones simétricas que, debido al polimorfismo de un solo argumento, deben colocarse en métodos de un lado:

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

[C++]

este se usa en el operador de asignación donde la mayor parte del tiempo tienes que verificar y evitar cosas extrañas (involuntarias, peligrosas o simplemente una pérdida de tiempo para el programa) como:

A a;
a = a;

Su operador de asignación se escribirá:

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

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

    return *this;
}

this en un compilador de C++

El compilador de C++ buscará silenciosamente un símbolo si no lo encuentra inmediatamente.A veces, la mayoría de las veces, es bueno:

  • usando el método de la clase madre si no lo sobrecargó en la clase secundaria.
  • promover un valor de un tipo en otro tipo

Pero a veces, Simplemente no quieres que el compilador adivine.Quiere que el compilador seleccione el símbolo correcto y no otro.

Para mí, esos momentos son cuando, dentro de un método, quiero acceder a un método miembro o variable miembro.Simplemente no quiero que se recoja algún símbolo aleatorio solo porque escribí printf en lugar de print. this->printf no habría compilado.

El punto es que, con las bibliotecas heredadas de C (§), el código heredado escrito hace años (§§) o cualquier cosa que pueda suceder en un lenguaje donde copiar y pegar es una característica obsoleta pero aún activa, a veces, decirle al compilador que no reproduzca El ingenio es una gran idea.

Estas son las razones que uso this.

(§) Todavía es una especie de misterio para mí, pero ahora me pregunto si el hecho de que incluya el encabezado <windows.h> en su código fuente es la razón por la que todos los símbolos de las bibliotecas C heredadas contaminarán su espacio de nombres global.

(§§) darse cuenta de que "necesita incluir un encabezado, pero incluir este encabezado romperá su código porque utiliza una macro tonta con un nombre genérico" es uno de esos ruleta rusa momentos de la vida de un codificador

'este.' Ayuda a encontrar miembros en la clase 'esta' con muchos miembros (generalmente debido a una cadena de herencia profunda).

Pulsar CTRL+Espacio no ayuda con esto, porque también incluye tipos;donde 'como' esto '. incluye solo miembros.

Normalmente lo elimino una vez que tengo lo que buscaba:pero este es solo mi estilo abriéndose paso.

En términos de estilo, si eres un llanero solitario, tú decides;Si trabaja para una empresa, respete la política de la empresa (mire las cosas en el control de fuente y vea lo que están haciendo otras personas).En términos de usarlo para calificar a los miembros, ni eso es correcto ni incorrecto.Lo único malo es la inconsistencia: esa es la regla de oro del estilo.Deja a los demás quisquillosos.En su lugar, dedique su tiempo a reflexionar sobre problemas reales de codificación y, obviamente, a la codificación.

Depende del estándar de codificación con el que estoy trabajando.Si usamos _ para indicar una variable de instancia, entonces "esto" se vuelve redundante.Si no usamos _ entonces tiendo a usar esto para indicar una variable de instancia.

lo uso para invocar Intellisense al igual que JuanMcG, pero volveré y borraré "esto->" cuando termine.Sigo la convención de Microsoft de anteponer las variables miembro con "m_", por lo que dejarlo como documentación sería simplemente redundante.

1 - Modismo de configuración común de Java:

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

2 - Al llamar a una función con este objeto como parámetro

notifier.addListener(this);

Lo uso cada vez que puedo.Creo que hace que el código sea más legible, y un código más legible equivale a menos errores y más facilidad de mantenimiento.

Cuando hay muchos desarrolladores trabajando en la misma base de código, necesita algunas pautas/reglas de código.Donde trabajo hemos decidido usar "esto" en campos, propiedades y eventos.

Para mí tiene sentido hacerlo así, hace que el código sea más fácil de leer cuando se diferencia entre variables de clase y variables de método.

Hay un uso que aún no se ha mencionado en C++ y es no hacer referencia al propio objeto ni eliminar la ambigüedad de un miembro de una variable recibida.

Puedes usar this para convertir un nombre no dependiente en un nombre dependiente de un argumento dentro de clases de plantilla que heredan de otras plantillas.

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

Las plantillas se compilan con un mecanismo de dos pasadas.Durante el primer paso, solo se resuelven y verifican los nombres que no dependen de argumentos, mientras que los nombres dependientes solo se verifican para verificar su coherencia, sin sustituir realmente los argumentos de la plantilla.

En ese paso, sin sustituir realmente el tipo, el compilador casi no tiene información de qué base<T> podría ser (tenga en cuenta que la especialización de la plantilla base puede convertirla en tipos completamente diferentes, incluso tipos indefinidos), por lo que simplemente se supone que es un tipo.En esta etapa la llamada no dependiente f que parece natural para el programador es un símbolo que el compilador debe encontrar como miembro de derived o al incluir espacios de nombres, lo cual no sucede en el ejemplo, y se quejará.

La solución es convertir el nombre no dependiente. f en un nombre dependiente.Esto se puede hacer de varias maneras, indicando explícitamente el tipo donde se implementa (base<T>::f --añadiendo el base<T> hace que el símbolo dependa de T y el compilador simplemente asumirá que existirá y pospondrá la verificación real para la segunda pasada, después de la sustitución del argumento.

La segunda forma, mucho más ordenada si heredas de plantillas que tienen más de un argumento o nombres largos, es simplemente agregar un this-> antes del símbolo.Como la clase de plantilla que está implementando depende de un argumento (hereda de base<T>) this-> depende del argumento y obtenemos el mismo resultado: this->f se verifica en la segunda ronda, después de la sustitución del parámetro de la plantilla.

No debes usar "esto" a menos que sea absolutamente necesario.

HAY una penalización asociada con la verbosidad innecesaria.Debes esforzarte por conseguir un código que sea exactamente tan largo como debe ser, y no más.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top