Domanda

Ero curioso di sapere come le altre persone usano il file Questo parola chiave.Tendo a usarlo nei costruttori, ma posso anche usarlo in tutta la classe in altri metodi.Qualche esempio:

In un costruttore:

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

Altrove

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}
È stato utile?

Soluzione

Esistono diversi usi di Questo parola chiave in C#.

  1. Per qualificare i membri nascosti da nomi simili
  2. Fare in modo che un oggetto passi se stesso come parametro ad altri metodi
  3. Per fare in modo che un oggetto restituisca se stesso da un metodo
  4. Per dichiarare gli indicizzatori
  5. Per dichiarare metodi di estensione
  6. Per passare parametri tra costruttori
  7. Per riassegnare internamente il valore, digitare (struct) valore.
  8. Per richiamare un metodo di estensione sull'istanza corrente
  9. Per trasformarsi in un altro tipo
  10. Per concatenare i costruttori definiti nella stessa classe

È possibile evitare il primo utilizzo non avendo variabili membro e locali con lo stesso nome nell'ambito, ad esempio seguendo convenzioni di denominazione comuni e utilizzando le proprietà (caso Pascal) invece dei campi (caso camel) per evitare collisioni con le variabili locali (anche camel caso).In C# 3.0 i campi possono essere convertiti facilmente in proprietà utilizzando proprietà implementate automaticamente.

Altri suggerimenti

Non voglio che questo suoni sarcastico, ma non importa.

Sul serio.

Guarda le cose importanti:il tuo progetto, il tuo codice, il tuo lavoro, la tua vita personale.Il successo di nessuno di essi dipenderà dall'utilizzo o meno della parola chiave "questo" per qualificare l'accesso ai campi.La parola chiave this non ti aiuterà a spedire in tempo.Non ridurrà i bug, non avrà alcun effetto apprezzabile sulla qualità o sulla manutenibilità del codice.Non ti darà un aumento né ti permetterà di trascorrere meno tempo in ufficio.

In realtà è solo una questione di stile.Se ti piace "questo", allora usalo.Se non lo fai, allora non farlo.Se ne hai bisogno per ottenere la semantica corretta, usalo.La verità è che ogni programmatore ha il suo stile di programmazione unico.Questo stile riflette le nozioni di quel particolare programmatore su come dovrebbe apparire il "codice esteticamente più gradevole".Per definizione, qualsiasi altro programmatore che legge il tuo codice avrà uno stile di programmazione diverso.Ciò significa che ci sarà sempre qualcosa che hai fatto che all'altro non piace, o che avrebbe fatto diversamente.Ad un certo punto qualcuno leggerà il tuo codice e si lamenterà di qualcosa.

Non mi preoccuperei per questo.Vorrei solo assicurarmi che il codice sia esteticamente gradevole secondo i tuoi gusti.Se chiedi a 10 programmatori come formattare il codice, otterrai circa 15 opinioni diverse.Una cosa migliore su cui concentrarsi è il modo in cui viene preso in considerazione il codice.Le cose sono astratte, giusto?Ho scelto nomi significativi per le cose?C'è molta duplicazione del codice?Ci sono modi in cui posso semplificare le cose?Penso che fare queste cose nel modo giusto avrà il massimo impatto positivo sul tuo progetto, sul tuo codice, sul tuo lavoro e sulla tua vita.Per coincidenza, probabilmente anche l'altro ragazzo si lamenterà di meno.Se il tuo codice funziona, è facile da leggere ed è ben fattorizzato, l'altro non controllerà come inizializzi i campi.Utilizzerà semplicemente il tuo codice, si meraviglierà della sua grandezza e poi passerà a qualcos'altro.

Lo uso solo quando assolutamente necessario, cioè quando un'altra variabile ne oscura un'altra.Come qui:

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 come sottolinea Ryan Fox, quando è necessario passarlo come parametro.(Le variabili locali hanno la precedenza sulle variabili membro)

Personalmente cerco di usarlo sempre Questo quando si fa riferimento alle variabili membro.Aiuta a chiarire il codice e renderlo più leggibile.Anche se non c'è ambiguità, qualcuno che legge il mio codice per la prima volta non lo sa, ma se vede Questo usati in modo coerente, sapranno se stanno guardando una variabile membro o meno.

Lo uso ogni volta che faccio riferimento a una variabile di istanza, anche se non ne ho bisogno.Penso che renda il codice più chiaro.

Non posso credere a tutte le persone che dicono che usarlo sempre è una "migliore pratica" e cose del genere.

Usa "questo" quando c'è ambiguità, come in L'esempio di Corey o quando è necessario passare l'oggetto come parametro, come in L'esempio di Ryan.Non c'è motivo di usarlo altrimenti perché la capacità di risolvere una variabile in base alla catena dell'ambito dovrebbe essere sufficientemente chiara da rendere superflua la qualificazione delle variabili con esso.

MODIFICARE:La documentazione C# su "this" indica un ulteriore utilizzo, oltre ai due che ho citato, per la parola chiave "this": per dichiarare gli indicizzatori

MODIFICARE:@Juan:Eh, non vedo alcuna incoerenza nelle mie affermazioni: ci sono 3 casi in cui utilizzerei la parola chiave "this" (come documentato nella documentazione C#), e quelli sono momenti in cui effettivamente Bisogno Esso.Attaccare "questo" davanti alle variabili in un costruttore quando non c'è ombreggiatura in corso è semplicemente uno spreco di tasti e una perdita di tempo durante la lettura, non fornisce alcun vantaggio.

Lo uso ogni volta StyleCop me lo dice. StyleCop deve essere obbedito.Oh si.

Ogni volta che hai bisogno di un riferimento all'oggetto corrente.

Uno scenario particolarmente utile è quando il tuo oggetto chiama una funzione e vuole passarvi dentro.

Esempio:

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

Tendo a usarlo anche ovunque, solo per assicurarmi che sia chiaro che si tratta dei membri dell'istanza con cui abbiamo a che fare.

Lo uso ovunque ci possa essere ambiguità (ovviamente).Non solo l'ambiguità del compilatore (sarebbe necessaria in quel caso), ma anche l'ambiguità per qualcuno che guarda il codice.

Un altro uso piuttosto raro della parola chiave this è quando è necessario invocare un'implementazione esplicita dell'interfaccia dall'interno della classe di implementazione.Ecco un esempio inventato:

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

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

Ecco quando lo uso:

  • Accesso ai metodi privati ​​dall'interno della classe (per differenziare)
  • Passare l'oggetto corrente a un altro metodo (o come oggetto mittente, in caso di un evento)
  • Quando si creano metodi di estensione: D

Non lo uso per i campi privati ​​perché antepongo i nomi delle variabili dei campi privati ​​con un carattere di sottolineatura (_).

[C++]

Sono d'accordo con la brigata "usalo quando devi".Decorare il codice inutilmente con Questo non è una grande idea perché il compilatore non ti avviserà quando ti dimentichi di farlo.Ciò introduce potenziale confusione per le persone in attesa Questo essere sempre lì, cioèdovranno farlo pensare a proposito.

Allora, quando lo useresti?Ho appena dato un'occhiata ad un codice casuale e ho trovato questi esempi (non sto esprimendo un giudizio sul fatto che lo siano Bene cose da fare o altro):

  • Passare "te stesso" a una funzione.
  • Assegnare "te stesso" a un puntatore o qualcosa del genere.
  • Casting, cioèlancio su/giù (sicuro o meno), eliminazione della costanza, ecc.
  • Il compilatore ha imposto la disambiguazione.

Lo utilizzo quando, in una funzione che accetta un riferimento ad un oggetto dello stesso tipo, voglio realizzarlo perfettamente chiaro a quale oggetto mi riferisco, dove.

Per esempio

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

(contro)

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

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

A colpo d'occhio cosa fa AABB right() fare riferimento?IL this aggiunge un po' di chiarimento.

Nella risposta di Jakub Šturc, il suo punto 5 sul passaggio dei dati tra costruttori probabilmente potrebbe aver bisogno di una piccola spiegazione.Questo avviene nell'overload dei costruttori ed è l'unico caso in cui si utilizza of this è obbligatorio.Nell'esempio seguente possiamo chiamare il costruttore con parametri dal costruttore senza parametri con un parametro predefinito.

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

Ho trovato che questa sia una funzionalità particolarmente utile in alcune occasioni.

Dovresti usarlo sempre, io lo uso per differenziare campi e parametri privati ​​(perché le nostre convenzioni di denominazione affermano che non usiamo prefissi per i nomi di membri e parametri (e si basano su informazioni trovate su Internet, quindi considero che un la migliore pratica))

Ho preso l'abitudine di usarlo liberamente in Visual C++ poiché così facendo si attiverebbero quelli IntelliSense. Premo il tasto ">" e sono pigro.(e incline agli errori di battitura)

Ma ho continuato a usarlo, poiché trovo utile vedere che sto chiamando una funzione membro anziché una funzione globale.

Tendo a sottolineare i campi con _ quindi non ho mai bisogno di usarlo.Inoltre R# tende comunque a rifattorizzarli via...

Praticamente uso solo Questo quando si fa riferimento a una proprietà del tipo dall'interno dello stesso tipo.Come menzionato da un altro utente, sottolineo anche i campi locali in modo che siano visibili senza bisogno Questo.

Lo uso solo quando richiesto, ad eccezione delle operazioni simmetriche che a causa del polimorfismo ad argomento singolo devono essere inserite in metodi di un lato:

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

[C++]

Questo viene utilizzato nell'operatore di assegnazione dove la maggior parte delle volte devi controllare e prevenire cose strane (non intenzionali, pericolose o semplicemente una perdita di tempo per il programma) come:

A a;
a = a;

L'operatore di assegnazione verrà scritto:

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 su un compilatore C++

Il compilatore C++ cercherà silenziosamente un simbolo se non lo trova immediatamente.A volte, la maggior parte delle volte, va bene:

  • usando il metodo della classe madre se non lo hai sovraccaricato nella classe figlia.
  • promuovere un valore di un tipo in un altro tipo

Ma a volte, Semplicemente non vuoi che il compilatore indovini.Vuoi che il compilatore prenda il simbolo giusto e non un altro.

Per me, quei momenti sono quando, all'interno di un metodo, voglio accedere a un metodo membro o a una variabile membro.Non voglio che venga preso qualche simbolo casuale solo perché ho scritto printf invece di print. this->printf non avrebbe compilato.

Il punto è che, con le librerie legacy del C (§), il codice legacy scritto anni fa (§§), o qualunque cosa possa accadere in un linguaggio in cui il copia/incolla è una funzionalità obsoleta ma ancora attiva, a volte, dice al compilatore di non riprodurre l'ingegno è un'ottima idea.

Questi sono i motivi che utilizzo this.

(§) è ancora una specie di mistero per me, ma ora mi chiedo se il fatto che includi l'intestazione <windows.h> nel tuo sorgente sia il motivo per cui tutti i simboli delle librerie C legacy inquineranno il tuo spazio dei nomi globale

(§§) rendersi conto che "è necessario includere un'intestazione, ma che l'inclusione di questa intestazione interromperà il codice perché utilizza una macro stupida con un nome generico" è uno di quelli roulette russa momenti della vita di un programmatore

'Questo.' Aiuta a trovare i membri di "questa" classe con molti membri (di solito a causa di una catena di eredità profonda).

Premere CTRL+Spazio non aiuta in questo, perché include anche i tipi;dove-come "questo". Include solo i membri.

Di solito lo cancello una volta che ho quello che cercavo:ma questo è semplicemente il mio stile che emerge.

In termini di stile, se sei un ranger solitario, decidi tu;se lavori per un'azienda attieniti alla politica aziendale (guarda le cose nel controllo del codice sorgente e guarda cosa stanno facendo gli altri).In termini di utilizzo per qualificare i membri, nessuno dei due è giusto o sbagliato.L'unica cosa sbagliata è l'incoerenza: questa è la regola d'oro dello stile.Lascia stare gli altri pignoli.Trascorri il tuo tempo riflettendo su problemi reali di codifica - e ovviamente codificando - invece.

Dipende dallo standard di codifica con cui sto lavorando.Se usiamo _ per denotare una variabile di istanza, "this" diventa ridondante.Se non stiamo usando _, tendo a usarlo per denotare la variabile di istanza.

Lo uso per invocare Intellisenso proprio come John McG, ma tornerò indietro e cancellerò "questo->" quando avrò finito.Seguo la convenzione Microsoft di anteporre alle variabili membro "m_", quindi lasciarla come documentazione sarebbe semplicemente ridondante.

1 - Linguaggio comune del setter Java:

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

2 - Quando si chiama una funzione con questo oggetto come parametro

notifier.addListener(this);

Lo uso ogni volta che posso.Credo che renda il codice più leggibile e un codice più leggibile equivale a meno bug e maggiore manutenibilità.

Quando siete molti sviluppatori che lavorano sulla stessa base di codice, avete bisogno di alcune linee guida/regole del codice.Dove lavoro abbiamo deciso di utilizzare "questo" su campi, proprietà ed eventi.

Per me ha senso farlo in questo modo, rende il codice più facile da leggere quando si distingue tra variabili di classe e variabili di metodo.

C'è un uso che non è già stato menzionato in C++ e cioè non fare riferimento al proprio oggetto o disambiguare un membro da una variabile ricevuta.

Puoi usare this per convertire un nome non dipendente in un nome dipendente dall'argomento all'interno delle classi modello che ereditano da altri modelli.

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

I modelli vengono compilati con un meccanismo a due passaggi.Durante il primo passaggio, vengono risolti e controllati solo i nomi dipendenti che non siano argomenti, mentre i nomi dipendenti vengono controllati solo per quanto riguarda la coerenza, senza effettivamente sostituire gli argomenti del modello.

A quel punto, senza sostituire effettivamente il tipo, il compilatore non ha quasi alcuna informazione su cosa base<T> potrebbe essere (nota che la specializzazione del modello base può trasformarlo in tipi completamente diversi, anche tipi non definiti), quindi presuppone semplicemente che sia un tipo.In questa fase la chiamata non dipendente f quello che sembra naturale al programmatore è un simbolo di cui il compilatore deve trovare un membro derived o racchiudendo spazi dei nomi, cosa che non accade nell'esempio, e si lamenterà.

La soluzione sta trasformando il nome non dipendente f in un nome dipendente.Questo può essere fatto in un paio di modi, dichiarando esplicitamente il tipo in cui è implementato (base<T>::f --aggiungendo il base<T> rende il simbolo dipendente da T e il compilatore presumerà semplicemente che esiste e posticiperà il controllo effettivo al secondo passaggio, dopo la sostituzione dell'argomento.

Il secondo modo, molto più semplice se si eredita da modelli che hanno più di un argomento o nomi lunghi, è semplicemente aggiungere un this-> prima del simbolo.Poiché la classe template che stai implementando dipende da un argomento (eredita da base<T>) this-> dipende dall'argomento e otteniamo lo stesso risultato: this->f viene controllato nel secondo turno, dopo la sostituzione del parametro del modello.

Non dovresti usare "questo" a meno che non sia assolutamente necessario.

C'è una penalità associata alla verbosità non necessaria.Dovresti cercare di ottenere un codice che sia esattamente lungo quanto necessario e non di più.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top