Pergunta

Fiquei curioso para saber como outras pessoas usam o esse palavra-chave.Costumo usá-lo em construtores, mas também posso usá-lo em toda a classe em outros métodos.Alguns exemplos:

Em um construtor:

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

Em outro lugar

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

Solução

Existem vários usos de esse palavra-chave em C#.

  1. Para qualificar membros ocultos por nome semelhante
  2. Para que um objeto se passe como parâmetro para outros métodos
  3. Para que um objeto retorne a si mesmo de um método
  4. Para declarar indexadores
  5. Para declarar métodos de extensão
  6. Para passar parâmetros entre construtores
  7. Para reatribuir internamente o valor do tipo de valor (struct).
  8. Para invocar um método de extensão na instância atual
  9. Para se lançar para outro tipo
  10. Para encadear construtores definidos na mesma classe

Você pode evitar o primeiro uso não tendo variáveis ​​de membro e locais com o mesmo nome no escopo, por exemplo, seguindo convenções de nomenclatura comuns e usando propriedades (caso Pascal) em vez de campos (caso camel) para evitar colidir com variáveis ​​locais (também camel caso).Em C# 3.0, os campos podem ser facilmente convertidos em propriedades usando propriedades implementadas automaticamente.

Outras dicas

Não quero que isso pareça sarcástico, mas não importa.

Seriamente.

Veja as coisas que são importantes:seu projeto, seu código, seu trabalho, sua vida pessoal.Nenhum deles terá sucesso dependendo de você usar ou não a palavra-chave "this" para qualificar o acesso aos campos.A palavra-chave this não o ajudará a enviar no prazo.Isso não reduzirá bugs, não terá nenhum efeito apreciável na qualidade ou na manutenção do código.Isso não lhe dará um aumento nem permitirá que você passe menos tempo no escritório.

Na verdade, é apenas uma questão de estilo.Se você gosta de "isto", então use-o.Se não, então não faça.Se você precisar obter a semântica correta, use-o.A verdade é que cada programador tem seu estilo de programação único.Esse estilo reflete as noções daquele programador específico sobre como deveria ser o "código mais esteticamente agradável".Por definição, qualquer outro programador que leia seu código terá um estilo de programação diferente.Isso significa que sempre haverá algo que você fez e que o outro cara não gostou ou que teria feito de forma diferente.Em algum momento, algum cara vai ler seu código e reclamar de alguma coisa.

Eu não me preocuparia com isso.Gostaria apenas de garantir que o código fosse o mais esteticamente agradável possível, de acordo com o seu gosto.Se você perguntar a 10 programadores como formatar código, receberá cerca de 15 opiniões diferentes.Uma coisa melhor para focar é como o código é fatorado.As coisas estão abstraídas, certo?Escolhi nomes significativos para as coisas?Existe muita duplicação de código?Existem maneiras de simplificar as coisas?Acho que acertar essas coisas terá o maior impacto positivo em seu projeto, seu código, seu trabalho e sua vida.Coincidentemente, provavelmente também fará com que o outro cara resmungue menos.Se o seu código funcionar, for fácil de ler e bem fatorado, o outro cara não examinará minuciosamente como você inicializa os campos.Ele apenas usará seu código, ficará maravilhado com sua grandeza e depois passará para outra coisa.

Eu só uso quando é absolutamente necessário, ou seja, quando outra variável está ocultando outra.Como aqui:

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

}

Ou como aponta Ryan Fox, quando você precisa passar this como parâmetro.(Variáveis ​​locais têm precedência sobre variáveis ​​de membro)

Pessoalmente, procuro sempre usar esse ao se referir a variáveis ​​de membro.Ajuda a esclarecer o código e torná-lo mais legível.Mesmo que não haja ambigüidade, alguém que lê meu código pela primeira vez não sabe disso, mas se vir esse usados ​​consistentemente, eles saberão se estão olhando para uma variável de membro ou não.

Eu uso isso toda vez que me refiro a uma variável de instância, mesmo que não seja necessário.Acho que isso deixa o código mais claro.

Não acredito em todas as pessoas que dizem que usá-lo sempre é uma "melhor prática" e tal.

Use "this" quando houver ambiguidade, como em O exemplo de Corey ou quando você precisa passar o objeto como parâmetro, como em O exemplo de Ryan.Não há razão para usá-lo de outra forma, porque ser capaz de resolver uma variável com base na cadeia de escopo deve ser claro o suficiente para que a qualificação de variáveis ​​com ela seja desnecessária.

EDITAR:A documentação C# sobre "this" indica mais um uso, além dos dois que mencionei, para a palavra-chave "this" - para declarar indexadores

EDITAR:@Juan:Huh, não vejo nenhuma inconsistência em minhas declarações - há 3 casos em que eu usaria a palavra-chave "this" (conforme documentado na documentação do C#), e esses são momentos em que você realmente precisar isto.Colocar "isto" na frente de variáveis ​​em um construtor quando não há sombreamento em andamento é simplesmente uma perda de pressionamento de teclas e uma perda de tempo ao lê-lo, pois não traz nenhum benefício.

Eu uso sempre EstiloCop me diz para fazer isso. EstiloCop deve ser obedecido.Oh sim.

Sempre que você precisar de uma referência ao objeto atual.

Um cenário particularmente útil é quando seu objeto está chamando uma função e deseja passar para ela.

Exemplo:

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

Costumo usá-lo em todos os lugares também, apenas para ter certeza de que está claro que estamos lidando com membros da instância.

Eu uso em qualquer lugar onde possa haver ambiguidade (obviamente).Não apenas ambiguidade do compilador (seria necessário nesse caso), mas também ambiguidade para quem olha o código.

Outro uso um tanto raro para a palavra-chave this é quando você precisa invocar uma implementação de interface explícita de dentro da classe de implementação.Aqui está um exemplo inventado:

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

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

É aqui que eu uso:

  • Acessando métodos privados de dentro da classe (para diferenciar)
  • Passando o objeto atual para outro método (ou como objeto remetente, no caso de um evento)
  • Ao criar métodos de extensão: D

Não uso isso para campos privados porque prefixo nomes de variáveis ​​de campos privados com um sublinhado (_).

[C++]

Concordo com a brigada "use quando for preciso".Decorar código desnecessariamente com esse não é uma boa ideia porque o compilador não avisará quando você esquecer de fazer isso.Isto introduz uma confusão potencial para as pessoas que esperam esse estar sempre lá, ou seja,eles terão que pensar sobre isso.

Então, quando você o usaria?Acabei de dar uma olhada em alguns códigos aleatórios e encontrei esses exemplos (não estou julgando se eles são bom coisas para fazer ou não):

  • Passando “você mesmo” para uma função.
  • Atribuir "você mesmo" a um ponteiro ou algo parecido.
  • Fundição, ou sejalançamento para cima/para baixo (seguro ou não), afastamento da constância, etc.
  • Desambiguação imposta pelo compilador.

Eu uso quando, em uma função que aceita uma referência a um objeto do mesmo tipo, quero fazer com que perfeitamente claro a qual objeto estou me referindo, onde.

Por exemplo

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

Resumindo o que a AABB faz right() referir-se?O this adiciona um pouco de esclarecimento.

Na resposta de Jakub Šturc, seu número 5 sobre a passagem de dados entre empreiteiros provavelmente precisaria de uma pequena explicação.Isso ocorre na sobrecarga de construtores e é o único caso em que o uso de this é mandatório.No exemplo a seguir podemos chamar o construtor parametrizado do construtor sem parâmetros com um parâmetro padrão.

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

Descobri que esse é um recurso particularmente útil ocasionalmente.

Você deve sempre usá-lo, eu uso para diferenciar campos e parâmetros privados (porque nossas convenções de nomenclatura afirmam que não usamos prefixos para nomes de membros e parâmetros (e eles são baseados em informações encontradas na internet, então considero que um Melhor prática))

Adquiri o hábito de usá-lo liberalmente no Visual C++, pois isso acionaria os do IntelliSense. Apertei a tecla '>' e sou preguiçoso.(e propenso a erros de digitação)

Mas continuei a usá-lo, pois acho útil ver que estou chamando uma função-membro em vez de uma função global.

Costumo sublinhar os campos com _ então nunca preciso usar isso.Além disso, o R # tende a refatorá-los de qualquer maneira ...

Eu praticamente só uso esse ao fazer referência a uma propriedade de tipo de dentro do mesmo tipo.Como outro usuário mencionou, também destaco os campos locais para que sejam visíveis sem a necessidade esse.

Eu uso isso apenas quando necessário, exceto para operações simétricas que devido ao polimorfismo de argumento único devem ser colocadas em métodos de um lado:

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

[C++]

esse é usado no operador de atribuição onde na maioria das vezes você tem que verificar e prevenir coisas estranhas (não intencionais, perigosas ou apenas uma perda de tempo para o programa) como:

A a;
a = a;

Seu operador de atribuição será escrito:

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 em um compilador C++

O compilador C++ procurará silenciosamente um símbolo se não o encontrar imediatamente.Às vezes, na maioria das vezes, é bom:

  • usando o método da classe mãe se você não o sobrecarregou na classe filha.
  • promovendo um valor de um tipo em outro tipo

Mas às vezes, Você simplesmente não quer que o compilador adivinhe.Você deseja que o compilador selecione o símbolo correto e não outro.

Para mim, esses momentos são quando, dentro de um método, desejo acessar um método membro ou variável de membro.Só não quero que algum símbolo aleatório seja pego só porque escrevi printf em vez de print. this->printf não teria compilado.

A questão é que, com bibliotecas legadas C (§), código legado escrito anos atrás (§§), ou o que quer que possa acontecer em uma linguagem onde copiar/colar é um recurso obsoleto, mas ainda ativo, às vezes, dizendo ao compilador para não jogar inteligência é uma ótima ideia.

Estas são as razões pelas quais eu uso this.

(§) ainda é uma espécie de mistério para mim, mas agora me pergunto se o fato de você incluir o cabeçalho <windows.h> em sua fonte é a razão pela qual todos os símbolos legados das bibliotecas C poluirão seu namespace global

(§§) perceber que "você precisa incluir um cabeçalho, mas incluir esse cabeçalho quebrará seu código porque ele usa alguma macro idiota com um nome genérico" é um daqueles roleta russa momentos da vida de um codificador

'esse.' Ajuda a encontrar membros nesta classe "esta" com muitos membros (geralmente devido a uma cadeia de herança profunda).

Pressionar CTRL+Espaço não ajuda nisso, porque também inclui tipos;onde-como 'isso.' inclui apenas membros.

Eu costumo excluí-lo quando consigo o que procurava:mas este é apenas o meu estilo rompendo.

Em termos de estilo, se você é um solitário – você decide;se você trabalha para uma empresa, siga a política da empresa (veja o que está no controle de origem e veja o que outras pessoas estão fazendo).Em termos de usá-lo para qualificar membros, nada está certo ou errado.A única coisa errada é a inconsistência – essa é a regra de ouro do estilo.Deixe os outros exigentes.Em vez disso, gaste seu tempo ponderando sobre problemas reais de codificação - e obviamente de codificação.

Depende do padrão de codificação em que estou trabalhando.Se estivermos usando _ para denotar uma variável de instância, então "this" se tornará redundante.Se não estivermos usando _ então costumo usar isso para denotar variável de instância.

Eu uso isso para invocar Intellisense Assim como JohnMcG, mas voltarei e apagarei "this->" quando terminar.Eu sigo a convenção da Microsoft de prefixar variáveis ​​de membro com "m_", portanto, deixá-la como documentação seria redundante.

1 - Idioma comum do setter Java:

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

2 – Ao chamar uma função tendo este objeto como parâmetro

notifier.addListener(this);

Eu uso sempre que posso.Acredito que isso torna o código mais legível, e código mais legível equivale a menos bugs e mais facilidade de manutenção.

Quando há muitos desenvolvedores trabalhando na mesma base de código, você precisa de algumas diretrizes/regras de código.Onde trabalho, decidimos usar 'this' em campos, propriedades e eventos.

Para mim, faz sentido fazer assim, pois torna o código mais fácil de ler quando você diferencia entre variáveis ​​de classe e variáveis ​​de método.

Há um uso que ainda não foi mencionado em C++: não se refere ao próprio objeto ou desambigua um membro de uma variável recebida.

Você pode usar this para converter um nome não dependente em um nome dependente de argumento dentro de classes de modelo que herdam de outros modelos.

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

Os modelos são compilados com um mecanismo de duas passagens.Durante a primeira passagem, apenas os nomes dependentes que não são de argumentos são resolvidos e verificados, enquanto os nomes dependentes são verificados apenas quanto à coerência, sem realmente substituir os argumentos do modelo.

Nessa etapa, sem realmente substituir o tipo, o compilador quase não tem informações sobre o que base<T> poderia ser (observe que a especialização do modelo base pode transformá-lo em tipos completamente diferentes, até mesmo em tipos indefinidos), então apenas assume que é um tipo.Nesta fase a chamada não dependente f que parece natural para o programador é um símbolo que o compilador deve encontrar como membro do derived ou no fechamento de namespaces - o que não acontece no exemplo - e ele reclamará.

A solução é transformar o nome não dependente f em um nome dependente.Isso pode ser feito de duas maneiras, declarando explicitamente o tipo onde ele é implementado (base<T>::f --adicionando o base<T> torna o símbolo dependente de T e o compilador apenas assumirá que ele existirá e adiará a verificação real para a segunda passagem, após a substituição do argumento.

A segunda maneira, muito mais classificada se você herdar de templates que possuem mais de um argumento, ou nomes longos, é apenas adicionar um this-> antes do símbolo.Como a classe de modelo que você está implementando depende de um argumento (ela herda de base<T>) this-> depende do argumento e obtemos o mesmo resultado: this->f é verificado na segunda rodada, após a substituição dos parâmetros do template.

Você não deve usar "this" a menos que seja absolutamente necessário.

Existe uma penalidade associada à verbosidade desnecessária.Você deve se esforçar para obter um código que seja exatamente tão longo quanto necessário, e não mais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top