2010-02-05 9 views
14

Ho visto alcune guide o blog che dicono che usare this per accedere ai membri di una classe è sbagliato. Tuttavia, ho anche visto alcuni posti dove i professionisti stanno accedendo con this. Tendo a preferire l'uso esplicito di this, in quanto sembra chiarire che la cosa a cui sto accedendo fa parte della classe.Devo usare "this" per chiamare proprietà, membri o metodi della classe?

this.MyProperty = this.GetSomeValue(); 

C'è qualche vantaggio o svantaggio di utilizzare this? È semplicemente una preferenza stilistica?

+2

Dipende se il tuo IDE evidenzia variabili e campi in modo diverso –

+5

Penso che questa sia una domanda molto soggettiva e non otterrai una risposta definitiva. Per me è tutto sulle preferenze e forse su quali standard di codifica stai lavorando. – David

+0

correlati: http://stackoverflow.com/questions/993352/when-should-i-make-explicit-use-of-the-this-pointer –

risposta

3

Essendo andato da utilizzare this per anni, alla ricerca di non molte persone (almeno nella mia esperienza) usarlo, alla fine ho cambiato. I benefici che posso vedere di avere questo-meno codice:

  • io uso sottolineature: _myVar per le variabili private, che non hanno bisogno di un this come sono sempre variabili membro.
  • Per le chiamate al metodo è ovvio che fa parte della classe. Dovresti anteporre il nome del tipo se non lo fosse.
  • (C#) Variabili e parametri privati ​​sono sempre caso cammello.
  • Se la tua classe è così grande si sta confondendo hai comunque un problema con la coesione e la separazione delle preoccupazioni.
  • (C#) visivi codici Studio colore tipi, in modo da sapere se si sta utilizzando una proprietà o tipo:

esempio

someclass.Method(1); 
SomeClass.StaticMethod(1); 

Vedo che se non si utilizza la sottolineatura convenzione di denominazione, e hanno un metodo di grandi dimensioni con un corpo pesante che potrebbe portare a una certa confusione.

I metodi o le proprietà statiche possono occasionalmente confondere le cose, ma molto raramente.

Sarà, ovviamente, ha sempre bisogno della parola chiave this quando passa riferimenti, ad esempio:

someclass.Method(this); 
var someclass = new SomeClass(this); 

(scrivo C#, ma la mia risposta è relativo a Java)

+3

Non utilizzare i caratteri di sottolineatura iniziali per denominare le variabili in C++. Se vuoi caratteri di sottolineatura, usa caratteri di sottolineatura finali, come in "myVar_" - questo è quello che faccio, ed è conforme. –

+0

@John: l'uso di un prefisso _m è anche conforme, il problema è quando qualcun altro arriva e chiama una variabile membro _Var. –

+1

@Steve: vero, ma perché giocare così vicino al traffico? :) –

1

È malvisto, quasi sempre in uso generale. Non uso mai "questo" in questo modo.

Le persone lo fanno perché ottengono Intellisense nel proprio editor digitando "questo" e quindi un "punto". Lo vedi anche in un sacco di posti quando i generatori di codice automatici stanno facendo la codifica.

Ora come per la domanda a perché utilizzando "questo" in tutto il codice è una cattiva idea. Prima di tutto, può essere usato come una stampella per coprire la mancanza di una buona convenzione di denominazione. Ad esempio, considero questo blocco di codice come un "horror di codifica":

class Fudge { 
    public decimal PoundsOfChocolate {get; set;} 
    Fudge (decimal PoundsOfChocoloate) { 
     this.PoundsOfChocolate = PoundsOfChocolate; 
    } 
} 

Yuck. Meglio usare un concordato convenzione di denominazione:

class Fudge { 
    public decimal PoundsOfChocolate {get; set;} 
    Fudge (decimal poundsOfChocoloate) { 
     PoundsOfChocolate = poundsOfChocolate; 
    } 
} 

Perché questo è meglio? Bene, nel caso banale come nell'esempio sopra, non importa molto. Le cose peggiorano quando le tue funzioni si allungano e tu hai variabili private in funzioni complesse che potrebbero entrare in collisione con i tuoi membri.

Inoltre, se si punge il codice con parole chiave "questo", diventa più difficile da leggere poiché il testo è più ripetitivo. Ed è solo più prolisso senza aggiungere semantica. IMO più verbosità senza semantica aggiunta è cattiva. I miei due centesimi. Downvote tutto quello che vuoi.

Ciò non vuol dire che "questo" non ha usi validi. Lontano da esso. Se lo usi per risolvere la differenza tra chiamare un membro base e un membro nell'oggetto corrente, allora ha il suo posto. Ha il suo posto anche nei generatori di codice. Ma come mi ha insegnato il whisky, l'uso eccessivo di qualcosa porta al dolore.

+5

Non spiega perché non si dovrebbe usare questo – David

+2

Sembra che questa sia solo un'opinione. Come fai a farlo? –

+1

L'uso di 'this' rende chiaro che stai accedendo a un membro, piuttosto che a una variabile locale. Può aggiungere chiarezza. L'unico svantaggio è che aggiunge caratteri extra al tuo codice.Dire che è disapprovato è solo falso. Ci possono essere situazioni in cui non è necessario, ma non è la stessa cosa. – mcv

3

Talvolta è necessario, ad es. in un costruttore (in C# o Java) se si assegna un campo da un parametro con lo stesso nome.

+1

Questo è uno dei motivi per cui avere una convenzione di denominazione speciale per i membri di vars è una buona cosa. –

+0

IME non è un problema abbastanza spesso da giustificare il prolungamento di tutti i miei programmi. – finnw

13

Se si aggiunge alla chiarezza del codice, utilizzarlo, se non lo fa. Ci sono alcuni posti lo fa aggiungere chiarezza - per esempio in C++:

struct Point { 
    int x, y; 
    Point & operator=(const Point & p) { 
     this->x = p.x; 
     this->y = p.y; 
     return *this; 
    } 
}; 

In casi come questo, quando si hanno due oggetti dello stesso tipo a cui fare riferimento Trovo che l'uso di this può chiarire le cose (tuttavia si noti che in C++ l'implementazione dell'operatore di assegnazione sopra non è necessaria).

+1

Un altro esempio è quando si eredita un'altra classe e si esegue l'override di un metodo e si desidera essere chiari su quale 'this.DoStuff()' e 'base.DoStuff()' devono essere chiamati. –

+1

La scrittura di Neil su C++ - sarebbe 'this-> DoStuff()' e 'Base :: DoStuff()'. E ad essere onesti, non penso che questo -> DoStuff() - aggiunga chiarezza. Devo ancora verificare se è virtuale, per esempio. – MSalters

0

Sono d'accordo con Dave. È più lungo

È semplicemente una questione di stile, non c'è altro effetto.

0

E 'utilizzato principalmente per costruttori e funzioni di inizializzazione (e preferisco questo stile a diverse sottolineature):

MyClass(hisValue) { this->hisValue = hisValue; } 

Utilizzando questo stile in tutto il mondo è solo una sintassi gonfiare ricorda la notazione ungherese. Se si mantengono le funzioni ragionevolmente brevi, le variabili locali ei parametri di funzione sono immediatamente riconoscibili per il lettore di codice. Se la dichiarazione non si trova all'interno dello schermo, si può presumere che sia un membro della classe - quindi "questa" notazione non aggiunge alcuna informazione utile.

+2

Poiché è ovviamente C++ (sì il -> ti ha dato via), dovresti usare MyClass (hisValue): hisValue (hisValue) {} Inoltre sei fortunato se fai in modo che tutti i tuoi compagni di squadra rispettino rigorosamente le linee X massime quota per funzione. Più facile quindi applicare un singolo carattere di sottolineatura finale per ogni variabile membro. –

+0

Solo pseudocodice casuale, mancanza di tipo prima che hisValue abbia dato via non è C++. E non ci dovrebbero essere "massime X linee per funzione", la dimensione della funzione dovrebbe essere in gran parte determinata - sorpresa! - capacità di "riconoscere immediatamente variabili locali e parametri di funzionamento". – ima

+0

E "più facile di" parte ... Non voglio nemmeno commentare. Dovresti considerare di cambiare lavoro, scrivere codice leggibile e comunicarlo al tuo team è parte di ciò che fanno gli ingegneri del software. Se lo trovi difficile - difficile, ma è qualcosa che devi imparare ad affrontare. – ima

2

Riguardo al C++, quando si utilizzano i modelli a volte è necessario utilizzare this per aiutare il compilatore con la risoluzione dei nomi:

template <typename T> 
class Base { 
    public: 
    void exit(); 
}; 

template <typename T> 
class Derived : Base<T> { 
    public: 
    void foo() { 
     exit(); // calls external exit() or error 
        // so you should use this->exit() if that was your intent 
    } 
}; 
+0

Non sono sicuro di capire cosa intendi. Le regole di risoluzione del tipo C++ la risolveranno in una chiamata a Base :: exit. Se vuoi la funzione esterna chiamata exit, devi digitare :: exit(). –

+1

No, non è così. Nomi dipendenti e tutto il resto Che è _esattamente_ perché vuoi renderlo inequivocabile. – MSalters

6

io uso sempre this. perché rende il codice più leggibile a mio parere. Rende immediatamente chiaro che

  • È un membro di questa istanza.
  • Chiarisce se la classe di base si chiama (base.) o il membro sovrascrivendo (this.)
  • Non è un membro statico.
  • Non è una chiamata a un membro di un'altra classe statica (this.Monster.Legs.Run(); rispetto a Monster.Legs.Run();).
+0

Voglio dire "questo" in risposta alla tua voce. Usarlo (almeno nel regno di C#) fornisce chiarezza assolutamente completa. Almeno per quanto riguarda C# non riesco a vedere una buona ragione per non usarlo. – chsh

+1

È specifico questo C#? In Java, 'this.Method()' non chiarisce che non è un metodo statico, ma rende solo chiaro che * hai pensato * che non era un metodo statico quando hai scritto il codice :-) –

+1

Se è così static, 'this.Method()' non compila in C# se questo è ciò che intendevi. – herzmeister

1

in Objective-C

... 
prop = value; // just an assignment 
... 

e

... 
self.prop = value; // !!! equivalent to method call [self setProp:value] 
... 

differiscono molto - si deve essere consapevoli di cosa e perché si sta facendo.

0

Io uso sempre questo per un semplice motivo:
(Esempio in C#, ma non voglio fare la differenza)

Prendiamo ad esempio una classe come questa:

class Foo { 
    private int count = 0; 
    public List<Int32> foos = new List<Int32>(); 

    public int DoCounting() { 
     foreach (Int32 foo in foos) { 
      if (foo > 50) ++count; 
     } 
     return count; 
    } 
} 

Ora un altro Il programmatore della tua azienda deve aggiungere rapidamente una funzione, vale a dire contare un altro ciclo. Lui non guarda il codice, ma semplicemente aggiunge il suo a causa della richiesta di critica tempo (o perché è 11:59 e vuole fare una pausa):

class Foo { 
    private int count = 0; 
    public List<Int32> foos = new List<Int32>(); 
    public List<Int32> bars = new List<Int32>(); 

    public int DoCounting() { 
     int count = bars.Count; 
     for (int i = 0; i < count; ++i) { 
      bars[i]++; 
     } 

     foreach (Int32 foo in foos) { 
      if (foo > 50) ++count; 
     } 
     return count; 
    } 
} 

Ora cosa succede? E quanto facilmente potrebbe essere evitato usando sempre questo?

Di esempio, l'esempio non è realistico ma si verifica facilmente in classi e metodi più complessi e causa errori di tracciamento dei bachi.

+0

Quindi, la prima interpretazione della classe Foo è impeccabile, dici? –

+0

Questo codice è tutt'altro che perfetto, è solo lì per dimostrare un punto. Non userei mai un campo pubblico (per una classe) e non darei mai un nome a foo, foos o bar (e raramente uso il conteggio). Il punto è: raramente lavori per conto tuo e altri programmatori potrebbero non leggere il tuo codice e sovrascrivere le tue variabili con variabili locali, quindi è sempre bene usare _questo_ per assicurarsi che, indipendentemente da ciò che fanno i tuoi colleghi, non avrà effetti collaterali sul tuo codice (ofc potrebbe ancora accadere, ma le probabilità sono migliori che non lo farà). – dbemerlin

+0

Non riesco davvero a vedere come usare (o non usare) questo può fare la differenza nella prima implementazione di Foo. Alterare lo stato solo per restituirlo (!!!) da un metodo è così ... strano e confuso di per sé che l'intera questione "questo" diventa irrilevante.Riesco a vedere il tuo punto (anche se preferirei andare con le convenzioni sui nomi) ma credo che l'esempio con cui sei arrivato sia troppo teso. –

2

La regola generale dovrebbe essere: utilizzare "questo" per evitare l'ambiguità, non utilizzare questo se è ovvio a ciò che si fa riferimento.

Ad esempio, quando si progammetta in Java, this.getSomeValue() non è necessario, poiché tutte le chiamate di funzione sono chiamate di metodo su "questo".D'altra parte, this.myProperty potrebbe essere utile se ci sono molte variabili locali all'interno del tuo metodo, o se ci sono variabili membro statiche, e vuoi chiarire che accedi a una variabile di istanza.

Naturalmente, a volte "questo" è inevitabile, come in

void setX(int x){ this.x = x; } 
+1

sarebbe evitabile usando void setX (int newX) {x = newX; };) I caratteri di sottolineatura – dbemerlin

+1

per le variabili membro risolvono questo problema e assicurano che non si abbia mai uno stackoverflow. –

+0

L'editor di eclissi "genera setter" produce questo tipo di codice, quindi si può assumere che sia java idiomatico. Non ho visto le variabili dei membri sottolineati da quando ho smesso di scrivere C++ (10 anni fa). – mfx

3

Io uso questo, perché mi sembra più leggibile E ...

StyleCop regola SA1101: PrefixLocalCallsWithThis dice:

Causa

Una chiamata a un membro di istanza della classe locale o una classe di base non è preceduto da 'questo . ', all'interno di un file di codice C#.

Descrizione regola

Una violazione di questa regola si verifica quando il codice contiene una chiamata a un membro di istanza della classe locale o una classe di base che non è prefisso ‘questo.’. Un'eccezione a questa regola si verifica quando esiste un override locale di un membro della classe base e il codice intende chiamare direttamente il membro della classe base, ignorando l'override locale. In questo caso, la chiamata può essere preceduta da "base" anziché "questo".

Per impostazione predefinita, StyleCop non consente l'utilizzo di caratteri di sottolineatura o m_ per contrassegnare i campi di classi locali, in favore del prefisso 'this.'. Il vantaggio dell'utilizzo di "this" è che si applica ugualmente a tutti i tipi di elementi inclusi metodi, proprietà, ecc. E non solo ai campi, rendendo tutte le chiamate ai membri della classe immediatamente riconoscibili, indipendentemente dall'editor utilizzato per visualizzare il codice . Un altro vantaggio è che crea una differenziazione rapida e riconoscibile tra membri di istanze e membri statici, che non sono prefissati.

Un ultimo vantaggio dell'utilizzo del prefisso "this." È quello digitandolo. farà in modo che Visual Studio mostri il popup IntelliSense, rendendo facile e veloce allo sviluppatore la scelta del membro della classe da chiamare.

Come correggere le violazioni

Per correggere una violazione di questa regola, inserire il ‘presente’. Prefisso prima della chiamata al membro della classe.

+0

Non conoscevo StyleCop. Sembra buono. – xyz

+0

Interessante. Il punto sui membri statici e di istanza è buono. –

0

L'utilizzo di questo rende i codici più puliti e leggibili. Inoltre non hai altra scelta che usare in una situazione in cui il nome del parametro è lo stesso di una variabile membro. Come si distinguono i due?

class Test { 
    int a; 

    void doA(int a) { 
    this.a = a; //if you do a=a its gonna be a bug really hard to catch 
    } 
} 
0

vorrei suggerire di usare sempre this a meno che il codice sarebbe comportarsi in modo diverso, se non l'avete fatto. Almeno agisce come zucchero sintattico per il programmatore/lettore per indicare che l'RHS proviene dalla classe corrente.

Inoltre, in alcune lingue (essendo Perl una), se si omette il riferimento all'oggetto, l'heirarchia dell'ereditarietà non viene utilizzata durante la risoluzione dell'RHS. per esempio. se methodName è definito nel parent, quindi $this->methodName() funzionerà, ma methodName() non riuscirà perché viene cercato solo il pacchetto corrente.

0

è davvero utile in una constructor cui codice come

this.field = field; 

diventa più leggibile. Metterei anche i metodi! La colorazione di this non fa male neanche.

Problemi correlati