Question

J'étais curieux de savoir comment les autres utilisaient le ce mot-clé.J'ai tendance à l'utiliser dans les constructeurs, mais je peux aussi l'utiliser dans toute la classe dans d'autres méthodes.Quelques exemples:

Dans un constructeur :

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

Autre part

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

La solution

Il existe plusieurs utilisations de ce mot-clé en C#.

  1. Pour qualifier les membres masqués par un nom similaire
  2. Pour qu'un objet se passe en paramètre à d'autres méthodes
  3. Pour qu'un objet revienne lui-même d'une méthode
  4. Pour déclarer les indexeurs
  5. Pour déclarer les méthodes d'extension
  6. Pour passer des paramètres entre les constructeurs
  7. Pour réaffecter en interne la valeur du type de valeur (struct).
  8. Pour appeler une méthode d'extension sur l'instance actuelle
  9. Pour se transformer en un autre type
  10. Pour chaîner des constructeurs définis dans la même classe

Vous pouvez éviter la première utilisation en n'ayant pas de variables membres et locales avec le même nom dans la portée, par exemple en suivant les conventions de dénomination courantes et en utilisant des propriétés (cas Pascal) au lieu de champs (cas Camel) pour éviter d'entrer en collision avec des variables locales (également Camel cas).En C# 3.0, les champs peuvent être facilement convertis en propriétés en utilisant propriétés implémentées automatiquement.

Autres conseils

Je ne veux pas paraître sarcastique, mais cela n’a pas d’importance.

Sérieusement.

Regardez les choses qui sont importantes :votre projet, votre code, votre travail, votre vie personnelle.Aucun d'entre eux ne verra son succès dépendre de l'utilisation ou non du mot-clé « this » pour qualifier l'accès aux champs.Le mot-clé this ne vous aidera pas à expédier à temps.Cela ne réduira pas les bogues, cela n'aura aucun effet appréciable sur la qualité ou la maintenabilité du code.Cela ne vous rapportera pas d’augmentation ni ne vous permettra de passer moins de temps au bureau.

C'est vraiment juste une question de style.Si vous aimez "ceci", alors utilisez-le.Si vous ne le faites pas, alors ne le faites pas.Si vous en avez besoin pour obtenir une sémantique correcte, utilisez-la.La vérité est que chaque programmeur a son propre style de programmation.Ce style reflète les notions de ce programmeur particulier sur ce à quoi devrait ressembler le « code le plus esthétique ».Par définition, tout autre programmeur qui lit votre code aura un style de programmation différent.Cela signifie qu'il y aura toujours quelque chose que vous avez fait et que l'autre n'aime pas ou qu'il aurait fait différemment.À un moment donné, un gars va lire votre code et se plaindre de quelque chose.

Je ne m'en inquiéterais pas.Je voudrais simplement m'assurer que le code est aussi esthétique que possible selon vos propres goûts.Si vous demandez à 10 programmeurs comment formater le code, vous obtiendrez environ 15 avis différents.Il est préférable de se concentrer sur la façon dont le code est pris en compte.Les choses sont-elles abstraites, n'est-ce pas ?Ai-je choisi des noms significatifs pour les choses ?Y a-t-il beaucoup de duplication de code ?Existe-t-il des moyens de simplifier les choses ?Je pense que bien faire ces choses aura le plus grand impact positif sur votre projet, votre code, votre travail et votre vie.Par coïncidence, cela amènera probablement aussi l'autre gars à se plaindre le moins.Si votre code fonctionne, est facile à lire et est bien pris en compte, l'autre personne ne va pas examiner la façon dont vous initialisez les champs.Il va simplement utiliser votre code, s'émerveiller de sa grandeur, puis passer à autre chose.

Je ne l'utilise qu'en cas d'absolue nécessité, c'est-à-dire lorsqu'une autre variable en occulte une autre.Comme ici :

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 comme le souligne Ryan Fox, lorsque vous devez transmettre ceci comme paramètre.(Les variables locales ont priorité sur les variables membres)

Personnellement, j'essaie de toujours utiliser ce en faisant référence aux variables membres.Cela permet de clarifier le code et de le rendre plus lisible.Même s'il n'y a pas d'ambiguïté, quelqu'un qui lit mon code pour la première fois ne le sait pas, mais s'il voit ce utilisés de manière cohérente, ils sauront s’ils examinent ou non une variable membre.

Je l'utilise chaque fois que je fais référence à une variable d'instance, même si je n'en ai pas besoin.Je pense que cela rend le code plus clair.

Je ne peux pas croire tous ceux qui disent que l'utiliser toujours est une "meilleure pratique" et autres.

Utilisez "ceci" en cas d'ambiguïté, comme dans L'exemple de Corey ou lorsque vous devez passer l'objet en paramètre, comme dans L'exemple de Ryan.Il n'y a aucune raison de l'utiliser autrement, car être capable de résoudre une variable basée sur la chaîne de portée devrait être suffisamment clair pour que qualifier les variables avec celle-ci ne soit pas nécessaire.

MODIFIER:La documentation C# sur "this" indique une utilisation supplémentaire, en plus des deux que j'ai mentionnées, pour le mot-clé "this" - pour déclarer les indexeurs

MODIFIER:@Juan :Hein, je ne vois aucune incohérence dans mes déclarations - il y a 3 cas où j'utiliserais le mot-clé "this" (comme documenté dans la documentation C#), et ce sont des moments où vous réellement besoin il.Coller "ceci" devant des variables dans un constructeur lorsqu'il n'y a pas d'observation est simplement une perte de frappe et une perte de temps lors de sa lecture, cela n'apporte aucun avantage.

Je l'utilise à chaque fois StyleCop me le dit. StyleCop doit être obéi.Oh oui.

Chaque fois que vous avez besoin d’une référence à l’objet actuel.

Un scénario particulièrement pratique est celui où votre objet appelle une fonction et veut s'y transmettre.

Exemple:

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

J'ai également tendance à l'utiliser partout, juste pour m'assurer qu'il est clair que nous avons affaire à des membres d'instance.

Je l'utilise partout où il peut y avoir une ambiguïté (évidemment).Pas seulement l'ambiguïté du compilateur (cela serait nécessaire dans ce cas), mais aussi l'ambiguïté pour quelqu'un qui regarde le code.

Une autre utilisation quelque peu rare du mot-clé this est lorsque vous devez invoquer une implémentation d'interface explicite à partir de la classe d'implémentation.Voici un exemple artificiel :

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

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

Voici quand je l'utilise :

  • Accéder aux méthodes privées depuis la classe (pour différencier)
  • Passer l'objet actuel à une autre méthode (ou en tant qu'objet expéditeur, en cas d'événement)
  • Lors de la création de méthodes d'extension :D

Je ne l'utilise pas pour les champs privés car je préfixe les noms de variables de champs privés avec un trait de soulignement (_).

[C++]

Je suis d'accord avec la brigade "utilisez-le quand il le faut".Décorer le code inutilement avec ce ce n'est pas une bonne idée car le compilateur ne vous avertira pas lorsque vous oubliez de le faire.Cela introduit une confusion potentielle pour les personnes qui s'attendent à ce être toujours là, c'est-à-direils devront pense à ce sujet.

Alors, quand l’utiliseriez-vous ?Je viens de jeter un œil à un code aléatoire et j'ai trouvé ces exemples (je ne porte pas de jugement sur le fait qu'ils soient bien choses à faire ou non) :

  • Passer "vous-même" à une fonction.
  • Attribuer "vous-même" à un pointeur ou quelque chose comme ça.
  • Casting, c'est-à-direcasting haut/bas (sûr ou non), rejet de la constance, etc.
  • Le compilateur a imposé l'homonymie.

Je l'utilise quand, dans une fonction qui accepte une référence à un objet du même type, je veux le faire parfaitement clair à quel objet je fais référence, où.

Par exemple

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

(contre)

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

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

En un coup d'œil, ce que fait AABB right() faire référence à?Le this ajoute un peu de clarification.

Dans la réponse de Jakub Šturc, son numéro 5 sur la transmission de données entre constructeurs pourrait probablement nécessiter une petite explication.Il s'agit d'une surcharge des constructeurs et c'est le seul cas où l'utilisation de this est obligatoire.Dans l'exemple suivant, nous pouvons appeler le constructeur paramétré à partir du constructeur sans paramètre avec un paramètre par défaut.

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

J'ai trouvé que c'était une fonctionnalité particulièrement utile à l'occasion.

Vous devriez toujours l'utiliser, je l'utilise pour différencier les champs et paramètres privés (car nos conventions de dénomination stipulent que nous n'utilisons pas de préfixes pour les noms de membres et de paramètres (et ils sont basés sur des informations trouvées sur Internet, donc je considère qu'un meilleur entrainement))

J'ai pris l'habitude de l'utiliser généreusement dans Visual C++, car cela déclencherait ceux d'IntelliSense. J'appuie sur la touche « > » et je suis paresseux.(et sujet aux fautes de frappe)

Mais j'ai continué à l'utiliser, car je trouve pratique de voir que j'appelle une fonction membre plutôt qu'une fonction globale.

J'ai tendance à souligner les champs avec _, donc je n'ai jamais vraiment besoin de l'utiliser.De toute façon, R# a tendance à les refactoriser...

Je n'utilise quasiment que ce lors du référencement d’une propriété de type à l’intérieur du même type.Comme l'a mentionné un autre utilisateur, je souligne également les champs locaux afin qu'ils soient visibles sans avoir besoin de ce.

Je ne l'utilise que lorsque cela est nécessaire, sauf pour les opérations symétriques qui, en raison du polymorphisme à argument unique, doivent être placées dans des méthodes d'un côté :

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

[C++]

ce est utilisé dans l'opérateur d'affectation où la plupart du temps vous devez vérifier et éviter des choses étranges (involontaires, dangereuses ou simplement une perte de temps pour le programme) comme :

A a;
a = a;

Votre opérateur d'affectation s'écrira :

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 sur un compilateur C++

Le compilateur C++ recherchera silencieusement un symbole s'il ne le trouve pas immédiatement.Parfois, la plupart du temps, c'est bien :

  • en utilisant la méthode de la classe mère si vous ne l'avez pas surchargée dans la classe enfant.
  • promouvoir une valeur d'un type dans un autre type

Mais parfois, Vous ne voulez tout simplement pas que le compilateur devine.Vous voulez que le compilateur récupère le bon symbole et pas un autre.

Pour moi, c'est dans ces moments-là que, au sein d'une méthode, je souhaite accéder à une méthode membre ou à une variable membre.Je ne veux tout simplement pas qu'un symbole aléatoire soit récupéré simplement parce que j'ai écrit printf au lieu de print. this->printf n'aurait pas compilé.

Le fait est que, avec les anciennes bibliothèques C (§), le code hérité écrit il y a des années (§§), ou tout ce qui pourrait arriver dans un langage où le copier/coller est une fonctionnalité obsolète mais toujours active, indiquant parfois au compilateur de ne pas jouer l'esprit est une excellente idée.

Ce sont les raisons pour lesquelles j'utilise this.

(§) c'est toujours une sorte de mystère pour moi, mais je me demande maintenant si le fait que vous incluiez l'en-tête <windows.h> dans votre source est la raison pour laquelle tous les symboles des bibliothèques C héritées pollueront votre espace de noms global.

(§§) réaliser que "vous devez inclure un en-tête, mais que l'inclusion de cet en-tête cassera votre code car il utilise une macro stupide avec un nom générique" en fait partie roulette russe moments de la vie d'un codeur

'ce.' Aide à trouver des membres sur «cette» classe avec beaucoup de membres (généralement en raison d'une chaîne d'héritage profonde).

Appuyer sur CTRL+Espace n'aide pas à cela, car cela inclut également les types ;où - comme «ceci». Comprend uniquement les membres.

Je le supprime généralement une fois que j'ai ce que je cherchais :mais c'est juste mon style qui se démarque.

En termes de style, si vous êtes un ranger solitaire, c'est vous qui décidez ;si vous travaillez pour une entreprise, respectez la politique de l'entreprise (regardez les éléments du contrôle de source et voyez ce que font les autres).En ce qui concerne son utilisation pour qualifier les membres, ni l’une ni l’autre n’est bonne ou mauvaise.La seule mauvaise chose est l’incohérence – c’est la règle d’or du style.Laissez les autres s'occuper des choses.Passez plutôt votre temps à réfléchir à de vrais problèmes de codage – et évidemment à coder.

Cela dépend de la norme de codage sous laquelle je travaille.Si nous utilisons _ pour désigner une variable d'instance, alors "this" devient redondant.Si nous n'utilisons pas _, j'ai tendance à l'utiliser pour désigner une variable d'instance.

Je l'utilise pour invoquer Intellisense juste comme JohnMcG, mais je reviendrai en arrière et effacerai "this->" quand j'aurai terminé.Je suis la convention de Microsoft consistant à préfixer les variables membres avec "m_", donc le laisser comme documentation serait tout simplement redondant.

1 - Idiome commun du setter Java :

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

2 - Lors de l'appel d'une fonction avec cet objet en paramètre

notifier.addListener(this);

Je l'utilise chaque fois que je peux.Je pense que cela rend le code plus lisible, et un code plus lisible équivaut à moins de bugs et à plus de maintenabilité.

Lorsque vous êtes nombreux à travailler sur la même base de code, vous avez besoin de directives/règles de code.Là où je travaille, nous avons décidé d'utiliser « ceci » sur les champs, les propriétés et les événements.

Pour moi, il est logique de procéder ainsi, cela rend le code plus facile à lire lorsque vous faites la différence entre les variables de classe et les variables de méthode.

Il existe une utilisation qui n'a pas déjà été mentionnée en C++, à savoir ne pas faire référence au propre objet ou lever l'ambiguïté d'un membre d'une variable reçue.

Vous pouvez utiliser this pour convertir un nom non dépendant en un nom dépendant d'un argument dans des classes de modèles qui héritent d'autres modèles.

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

Les modèles sont compilés avec un mécanisme en deux passes.Lors de la première passe, seuls les noms non dépendants des arguments sont résolus et vérifiés, tandis que les noms dépendants sont vérifiés uniquement pour leur cohérence, sans réellement remplacer les arguments du modèle.

À cette étape, sans réellement remplacer le type, le compilateur n'a presque aucune information sur ce que base<T> pourrait l'être (notez que la spécialisation du modèle de base peut le transformer en types complètement différents, même en types indéfinis), il suppose donc simplement qu'il s'agit d'un type.A ce stade, l'appel non dépendant f qui semble tout à fait naturel au programmeur est un symbole que le compilateur doit trouver en tant que membre de derived ou en entourant des espaces de noms - ce qui ne se produit pas dans l'exemple - et il se plaindra.

La solution consiste à transformer le nom non dépendant f en un nom dépendant.Cela peut être fait de plusieurs manières, en indiquant explicitement le type où il est implémenté (base<T>::f --ajout du base<T> rend le symbole dépendant de T et le compilateur supposera simplement qu'il existera et reportera la vérification réelle pour la deuxième passe, après substitution d'arguments.

La deuxième méthode, qui permet de trier beaucoup si vous héritez de modèles comportant plus d'un argument ou des noms longs, consiste simplement à ajouter un this-> avant le symbole.Comme la classe modèle que vous implémentez dépend d'un argument (elle hérite de base<T>) this-> dépend de l'argument, et nous obtenons le même résultat : this->f est vérifié au deuxième tour, après substitution des paramètres du modèle.

Vous ne devez pas utiliser « ceci » sauf si vous y êtes absolument obligé.

Il existe une pénalité associée à une verbosité inutile.Vous devez vous efforcer d’obtenir un code exactement aussi long qu’il doit l’être, et pas plus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top