Quando você usa a palavra-chave "this"? [fechadas]


249

Fiquei curioso para saber como outras pessoas usam a palavra - chave this . 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);
}

2
Encontrei bons exemplos quando você realmente precisa this no MSDN. Por favor, siga este link ... ;-)
Matt

12
Se você tiver que entender e otimizar ou reescrever outra pessoa, principalmente código mal escrito, você ficaria feliz em ter thisou qualquer outro qualificador para que, a partir de uma simples olhada, você saiba o escopo da variável (Qualificadores de classe especialmente omitidos para constantes (mesmo pacote ou hierarquia) ou super/ basequalificadores). E usar a sintaxe comumente usada _foonão parece tão elegante para mim. Pressionar _pelo intellisense é mais demorado do que entrar this. E por que se preocupar! Com as funções de formatação de salvamento automático do eclipse, não é necessário _, caso você tenha esquecido o qualificador.
djmj

Depois de ler as respostas e os comentários abaixo, além de ler a documentação do MSDN: docs.microsoft.com/en-us/version/events/visualstudio/… sobre esta palavra - chave que não foi atualizada em 6 anos, sugiro para nunca usar a palavra - chave this . É inútil. Não torne os parâmetros com o mesmo nome, isso é confuso e estúpido. Por que você faria isso? Além disso, não passe a instância usando isso , também é confuso e estúpido.
Yusha 10/07/19

Respostas:


218

Existem vários usos dessa 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 partir 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 redesignar internamente o valor do tipo (struct) .
  8. Para chamar um método de extensão na instância atual
  9. Para lançar-se para outro tipo
  10. Para encadear construtores definidos na mesma classe

Você pode evitar o primeiro uso por não ter variáveis ​​membros 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 colisão com variáveis ​​locais (também camel caso). No C # 3.0, os campos podem ser convertidos em propriedades facilmente usando propriedades implementadas automaticamente .


49
8. Para invocar um método de extensão na instância atual ( this.Foo();funcionará, mas Foo()não funcionará)
Marc Gravell

4
Também para converter-se para outro tipo, por exemplo, um método implementado explicitamente será chamado como ((ICollection<T>)this).Add(bla).
Nawfal

4
Para encadear a construção para outro construtor definido no mesmo tipo. public ClassName(...) : this(...).
Lasse V. Karlsen

1
@ E não afetará o desempenho no tempo de execução. Supondo que não haja ambiguidade, a saída do compilador é a mesma, independentemente de você escrever, por exemplo this.someField = someValueou someField = someValue. Isso pode afetar o desempenho do compilador, uma vez que o compilador analisará o código-fonte de maneira diferente, mas qualquer diferença certamente será insignificante.
Phoog 5/05

7
Você pode evitar o primeiro problema acessando campos por meio de propriedades apenas se aderir a uma convenção de estilo em que propriedades não podem ter o mesmo nome que parâmetros. Acontece que a convenção predominante no estilo C # atende a esse requisito. Nem todo C # é escrito sob essa convenção, no entanto. Não há nada inerente nas propriedades em si que tornaria a thispalavra - chave desnecessária; um parâmetro construtor chamado xocultará um membro chamado xse esse membro é um campo, uma propriedade ou um evento.
Phoog 5/05

246

Não quero que isso pareça irritante, mas isso não importa.

Seriamente.

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

É realmente apenas uma questão de estilo. Se você gosta de "this", use-o. Se não, então não. Se você precisar obter a semântica correta, use-a. A verdade é que todo programador tem seu próprio estilo de programação. Esse estilo reflete as noções desse programador específico de como deveria ser o "código mais esteticamente agradável". Por definição, qualquer outro programador que lê seu código terá um estilo de programação diferente. Isso significa que sempre haverá algo que você fez que o outro cara não gosta, ou teria feito de maneira diferente. Em algum momento, um cara vai ler seu código e resmungar sobre alguma coisa.

Eu não me preocuparia com isso. Gostaria apenas de garantir que o código seja o mais esteticamente possível, de acordo com o seu gosto. Se você perguntar a 10 programadores como formatar o 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? Eu 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, código, trabalho e vida. Coincidentemente, provavelmente também fará com que o outro cara reclame menos. Se o seu código funcionar, for fácil de ler e for bem fatorado, o outro cara não examinará como você inicializa os campos. Ele só vai usar o seu código, maravilhar-se com a sua grandeza,


35
A thispalavra-chave é semanticamente significativa. Veja o comentário de @ JasonBunting abaixo. Você confunde o uso estilístico excessivo thiscom seu objetivo real. Sua observação não é apenas irreverente, está errada!
precisa saber é o seguinte

12
Se você tiver uma chance, convém reler minha resposta. Eu falo sobre usá-lo nos casos em que é necessário para a semântica correta. Você também pode querer examinar a questão de origem. Está mostrando o uso em exemplos onde não é semanticamente necessário. Então, não sei exatamente o que disse que estava "errado". Minha resposta certamente não é irreverente.
Scott Wisniewski

9
Você sabe como sua resposta me soa? Nas entrelinhas, li "Como você se atreve a fazer uma pergunta como essa?" - Isso não é realmente construtivo na minha opinião. Ninguém sabe tudo - é por isso que temos o Stackoverflow: Para ajudar os outros e obter ajuda. Alguns tópicos que você conhece, alguns conhecem outros. Ajude um ao outro, não lute um com o outro. Por favor, pense sobre isso.
Matt

9
Não pretendo parecer irreverente, mas esta é uma das piores respostas até agora. Não vejo como comparar isso com seu trabalho ou vida pessoal seja útil. Só porque algumas coisas são menos importantes que outras, não significa que elas não são importantes . Ter um estilo de programação consistente não é sem importância (leia um livro sobre legibilidade / manutenção de código de sua escolha).
aioobe

4
Eu acho que você pode ter entendido mal o meu ponto. Não é que "ter um estilo consistente" seja ruim. Não digo nada nesse sentido. É que a questão operacional de "meu guia de estilo deve ordenar 'isso'". como prefixo para todos os acessos a campos? " é arbitrário e caprichoso.
22415 Scott Scottnniewski

96

Só o uso quando absolutamente necessário, ou seja, quando outra variável está sombreando 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 Ryan Fox aponta, quando você precisa passar isso como um parâmetro. (Variáveis ​​locais têm precedência sobre variáveis ​​de membro)


6
Nesse caso, por que não dar nomes diferentes para as variáveis ​​de entrada do construtor?
Wz366

54

Pessoalmente, tento sempre usar isso ao me referir a variáveis ​​de membro. Isso ajuda a esclarecer o código e torná-lo mais legível. Mesmo se não houver ambiguidade, alguém lendo meu código pela primeira vez não sabe disso, mas se vir isso usado de forma consistente, saberá se está olhando para uma variável de membro ou não.


9
mas se você se esqueça de usá-lo em algum momento, eles vão ficar confuso
surfen

2
@surfen que pode ser evitado por verificações de estilo adicionais, por exemplo, em Java você pode usar Checkstyle e executá-lo após uma compilação completa (e em qualquer língua / OO iterativo populares haverá ferramentas semelhantes)
Maarten Bodewes

5
@surfen como se você a esquecesse em casos ambíguos. Eu posso quebrar qualquer argumento dizendo "mas se você esquecer ...".
Askolein 21/01

6
A maioria das pessoas parece nunca ler, otimizar ou reescrever o código de outra pessoa! As eliminatórias economizam tempo e motivação! Sem qualificador, é como mágica se você vir alguma linha de código arbitrária. Então você perde todo o tempo apenas checando de onde vêm essas variáveis.
djmj

3
Sei que este é um post muito antigo, mas não posso deixar de comentar a ironia dessa resposta (com a qual concordo). Na Jihad contra a má notação húngara, qualquer um que ousasse prefixar suas variáveis ​​de membro com "m_" foi rapidamente criticado porque distinguir variáveis ​​de membro simplesmente não era útil ou necessário.
Michael J.

38

Eu o uso toda vez que me refiro a uma variável de instância, mesmo que não precise. Eu acho que isso torna o código mais claro.


Eu quero diferenciar variáveis ​​de classe o máximo possível, para que o código seja mais claro. Eu costumava usar o prefixo m_ (variável de membro), por exemplo, a string privada m_name. Agora eu apenas uso isso, por exemplo, se eu tiver a classe Test {private string a; public someMethod () {this.a = "foo"; }
Banda larga

36

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

Use "this" quando houver ambiguidade, como em exemplo de Corey ou quando precisar passar o objeto como parâmetro, como no exemplo de Ryan . Não há razão para usá-lo de outra forma, porque a capacidade de resolver uma variável com base na cadeia de escopo deve ser clara o suficiente para que as variáveis ​​qualificadas com ele sejam desnecessárias.

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

Edição: @ Juan: Huh, eu não vejo nenhuma inconsistência nas minhas declarações - há 3 casos em que eu usaria a palavra-chave "this" (conforme documentada na documentação do C #), e são momentos em que você realmente precisa . Colocar "isto" na frente de variáveis ​​em um construtor quando não há sombreamento é simplesmente um desperdício de pressionamentos de tecla e um desperdício de tempo ao lê-lo, não oferece nenhum benefício.


21
@ JasonBunting : Você não pode fazer algo, por vezes, e não alguns outros ... É confuso ... Eu espero nunca trabalhar em seu código Você pode nem sempre Asume que uma pessoa que lê o seu código no futuro vai entender o que você escreveu, você precisa ser o mais claro possível, e uma maneira de alcançá-lo é ser consistente
juan

@juan, 10 anos depois. Você ainda acha que usar "isso" é uma boa prática? :)
Scott Adams

2
@ScottAdams Eu ainda acredito em consistência e clareza, sim
juan

Que tal determinar o escopo de uma variável (seja local ou variável de membro) apenas olhando para ela? Não é 'isso' justificado para esse fim? Ou você quer dizer que, se escrevermos métodos menores, seria fácil entender o escopo da variável?
BornToCode 26/06/19

27

Eu o uso sempre que o StyleCop me diz. StyleCop deve ser obedecido. Ai sim.


1
E ReSharper me diz para não usá-lo. Meio confuso quando estou usando o StyleCop e o ReSharper ao mesmo tempo :) Mas eu me inclino à resposta do Coreys acima, para usar a palavra-chave 'this' apenas quando for absolutamente necessário.
Gunnar

@Gunnar, há uma opção para desativar a eliminação de "isso" redundante. em R #
Winger Sendon

@EmperorAiman ​​- Sim, eu sei. Meu argumento foi que essas duas ferramentas populares de formatação são por padrão, sugerindo duas coisas diferentes e que podem ser confusas. "Ser ou não ser ..." :)
Gunnar

11

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 por ela mesma.

Exemplo:

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

7

Também costumo usá-lo em todos os lugares, apenas para garantir que esteja claro que são os membros de instância com os quais estamos lidando.


5

Eu o 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 alguém que olha o código.


5

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

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

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

4

Aqui é quando eu o 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

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


4

[C ++]

Concordo com a brigada "use-a quando for necessário". Decorar códigos desnecessariamente com isso não é uma boa idéia, porque o compilador não avisa quando você se esquece de fazê-lo. Isso introduz uma potencial confusão para as pessoas que esperam que isso sempre esteja lá, ou seja, elas terão que pensar sobre isso.

Então, quando você usaria? Acabei de dar uma olhada em algum código aleatório e encontrei esses exemplos (não estou julgando se essas são boas coisas para fazer ou não):

  • Passando "você mesmo" para uma função.
  • Atribuindo "você mesmo" a um ponteiro ou algo parecido.
  • Fundição, ou seja, fundição para cima / baixo (segura ou não), fundição fora, etc.
  • Desambiguação imposta pelo compilador.

3

Você deve sempre usá-lo, eu o 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, por isso considero que um Melhor prática))


3

Uso quando, em uma função que aceita uma referência a um objeto do mesmo tipo, quero deixar perfeitamente claro 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() ;
  }
} ;

(vs)

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

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

À primeira vista a que a AABB se right()refere? O thisacrescenta um pouco de um esclarecedor.


3

Na resposta de Jakub Šturc, o número 5 sobre a passagem de dados entre contratantes provavelmente poderia usar uma pequena explicação. Isso ocorre na sobrecarga de construtores e é o caso em que o uso de thisé obrigatório. No exemplo a seguir, podemos chamar o construtor parametrizado a partir 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 este é um recurso particularmente útil em algumas ocasiões.


2

Eu adquiri o hábito de usá-lo liberalmente no Visual C ++, pois isso ativaria 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 de membro em vez de uma função global.


1

Costumo sublinhar os campos com _ para que realmente nunca precise usá-lo. Também o R # tende a refatorá-los de qualquer maneira ...


1

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


1

Eu o uso somente 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;
} 

1

[C ++]

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

A a;
a = a;

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

1

this em um compilador C ++

O compilador C ++ procurará silenciosamente um símbolo se ele 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 filho.
  • promovendo um valor de um tipo para outro tipo

Mas, às vezes, você simplesmente não quer que o compilador adivinhe. Você deseja que o compilador selecione o símbolo certo 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 escolhido apenas porque escrevi em printfvez de print. this->printfnão teria compilado.

O ponto é que, com as bibliotecas C herdadas (§), o código herdado escrito anos atrás (§§) ou o que poderia acontecer em um idioma em que copiar / colar é um recurso obsoleto, mas ainda ativo, às vezes, dizendo ao compilador para não jogar inteligência é uma ótima idéia.

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

(§) ainda é um tipo 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 das bibliotecas C herdadas poluirão seu espaço de nome global

(§§) perceber que "você precisa incluir um cabeçalho, mas que a inclusão desse cabeçalho interromperá seu código porque usa alguma macro burra com um nome genérico" é um daqueles momentos da roleta russa na vida de um codificador


1

'isto.' ajuda a encontrar membros dessa classe com muitos membros (geralmente devido a uma profunda cadeia de herança).

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

Normalmente, eu a apago uma vez que tenho o que estava procurando: mas esse é apenas o meu estilo.

Em termos de estilo, se você é um guarda solitário - você decide; se você trabalha para uma empresa, atenha-se à política da empresa (observe as coisas no controle de origem e veja o que as outras pessoas estão fazendo). Em termos de usá-lo para qualificar membros, nenhum deles está certo ou errado. A única coisa errada é a inconsistência - essa é a regra de ouro do estilo. Deixe o nit-picking outros. Gaste seu tempo pensando em problemas reais de codificação - e obviamente em codificação -.


1

Eu uso sempre que posso. Eu acredito que torna o código mais legível, e mais legível é igual a menos bugs e mais manutenibilidade.


1

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 fazê-lo assim, facilita a leitura do código quando você diferencia entre variáveis ​​de classe e variáveis ​​de método.


0

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


0

Eu o uso para invocar o Intellisense como o JohnMcG , mas voltarei e apago "this->" quando terminar. Sigo a convenção da Microsoft de prefixar variáveis-membro com "m_", deixando-a como documentação seria redundante.


0

1 - Idioma comum do setter Java:

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

2 - Ao chamar uma função com este objeto como parâmetro

notifier.addListener(this);

0

Há um uso que ainda não foi mencionado em C ++ e que não é para se referir ao próprio objeto ou desambiguar um membro de uma variável recebida.

Você pode usar thispara 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 nomes dependentes de não argumento são resolvidos e verificados, enquanto nomes dependentes são verificados apenas por coerência, sem realmente substituir os argumentos do modelo.

Nessa etapa, sem realmente substituir o tipo, o compilador quase não tem informações do que base<T>poderia ser (observe que a especialização do modelo base pode transformá-lo em tipos completamente diferentes, mesmo tipos indefinidos); portanto, apenas assume que é um tipo . Nesse estágio, a chamada não dependente fque parece natural ao programador é um símbolo que o compilador deve encontrar como membro dederived ou nos espaços de nomes anexos - o que não acontece no exemplo - e ele irá reclamar.

A solução está transformando o nome não dependente fem um nome dependente. Isso pode ser feito de duas maneiras, declarando explicitamente o tipo em que é implementado (- base<T>::fadicionando o base<T>torna o símbolo dependente Te o compilador apenas assume que ele existirá e adia a verificação real para a segunda passagem, depois substituição de argumento.

A segunda maneira, muito mais ordenada, se você herdar de modelos com 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 (herdado 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 modelo.


-2

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

Existe uma penalidade associada a verbosidade desnecessária. Você deve procurar um código que seja exatamente o tempo necessário e não mais.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.