323 votes

Y a-t-il des raisons d'utiliser des propriétés privées en C# ?

Je viens de réaliser que le C# construction de la propriété peut également être utilisé avec un privé modificateur d'accès :

private string Password { get; set; }

Bien que cela soit techniquement intéressant, je ne peux pas imaginer quand je l'utiliserais puisqu'un domaine privé implique même moins de cérémonie :

private string _password;

et je ne peux pas imaginer que j'aurai un jour besoin d'être capable d'interner. obtenir mais pas set o set mais pas obtenir un terrain privé :

private string Password { get; }

ou

private string Password { set; }

mais peut-être y a-t-il un cas d'utilisation avec classes imbriquées / héritées ou peut-être lorsqu'un get/set peut contenir logique au lieu de simplement redonner la valeur de la propriété, bien que j'aurais tendance à garder les propriétés strictement simples et à laisser les méthodes explicites faire toute la logique, par ex. GetEncodedPassword() .

Quelqu'un utilise-t-il les propriétés privées en C# pour une raison quelconque ou s'agit-il simplement d'une de ces constructions techniquement possibles mais rarement utilisées dans le code réel ?

Addendum

Bonnes réponses, en les lisant, j'ai retenu ces utilisations pour les propriétés privées :

  • lorsque des champs privés doivent être chargés paresseusement
  • lorsque les champs privés nécessitent une logique supplémentaire ou sont des valeurs calculées.
  • car les champs privés peuvent être difficiles à déboguer
  • afin de "présenter un contrat à soi-même"
  • pour convertir/simplifier en interne une propriété exposée dans le cadre de la sérialisation
  • envelopper les variables globales à utiliser dans votre classe

2 votes

La technique encouragée par les propriétés privées est auto-encapsulation - voir : sourcemaking.com/refactoring/self-encapsulate-field

0 votes

0 votes

@LBushkin Auto-encapsulation semble concerner les propriétés protégées (ou publiques) et non les propriétés privées.

265voto

Shaun Bowe Points 3390

Je les utilise si j'ai besoin de mettre en cache une valeur et que je veux la charger paresseusement.

private string _password;
private string Password
{
    get
    {
        if (_password == null)
        {
            _password = CallExpensiveOperation();
        }

        return _password;
    }
}

3 votes

+1 C'est aussi mon utilisation standard ! J'aime aussi la possibilité d'ajouter une logique supplémentaire plus tard, comme @Reed Copsey l'a mentionné précédemment.

62 votes

Un bon modèle commun pour cela est return _password ?? (_password = CallExpensiveOperation());

20 votes

@Marc depuis C# 6, vous n'avez même pas besoin d'écrire un get et un return. private string Password => _password ?? (_password = CallExpensiveOperation());

180voto

Eric Lippert Points 300275

L'utilisation principale de ceci dans mon code est l'initialisation paresseuse, comme d'autres l'ont mentionné.

Une autre raison de préférer les propriétés privées aux champs est que les propriétés privées sont beaucoup, beaucoup plus faciles à déboguer que les champs privés. Je veux souvent savoir des choses comme "ce champ est défini de manière inattendue ; qui est le premier appelant qui définit ce champ ?" et c'est beaucoup plus facile si vous pouvez simplement mettre un point d'arrêt sur le définisseur et appuyer sur "go". Vous pouvez y intégrer la journalisation. Vous pouvez y mettre des mesures de performance. Vous pouvez mettre en place des contrôles de cohérence qui s'exécutent dans la version de débogage.

En gros, cela se résume à : le code est bien plus puissant que les données . Toute technique qui me permet d'écrire le code dont j'ai besoin est bonne. Les champs ne vous permettent pas d'écrire du code, les propriétés le font.

10 votes

Est-ce que vous dites "le code est bien plus puissant que les données" ? Une recherche sur Google renvoie à des références qui vous désignent. Je veux juste savoir pour pouvoir le citer correctement quand j'en aurai besoin.

38 votes

@Joan : Je ne sais pas. Soit je l'ai inventé, soit j'ai entendu quelqu'un d'autre le dire et je me suis dit "wow, je devrais carrément piquer ça, et ensuite oublier à qui je l'ai piqué".

51voto

Reed Copsey Points 315315

peut-être y a-t-il un cas d'utilisation avec des classes imbriquées / héritées ou peut-être qu'un get/set peut contenir une logique au lieu de simplement donner la valeur de la propriété.

Je l'utilise personnellement même lorsque je n'ai pas besoin de logique sur le getter ou le setter d'une propriété. L'utilisation d'une propriété, même privée, permet d'assurer l'avenir de votre code, de sorte que vous pouvez ajouter la logique à un getter ultérieurement, si nécessaire.

Si je pense qu'une propriété peut éventuellement nécessiter une logique supplémentaire, je l'intègre parfois dans une propriété privée au lieu d'utiliser un champ, juste pour ne pas avoir à modifier mon code par la suite.


Dans un cas semi-relié (bien que différent de votre question), j'utilise très fréquemment les setters privés sur les propriétés publiques :

public string Password 
{
    get; 
    private set;
}

Cela vous donne un getter public, mais garde le setter privé.

1 votes

+1 est logique : "Si je pense qu'une propriété peut éventuellement nécessiter une logique supplémentaire, je vais parfois l'envelopper dans une propriété privée au lieu d'utiliser un champ, juste pour ne pas avoir à modifier mon code plus tard."

29voto

JaredPar Points 333733

Les valeurs calculées constituent un bon usage des propriétés privées à obtenir uniquement. Plusieurs fois, j'ai eu des propriétés privées en lecture seule qui faisaient juste un calcul sur d'autres champs de mon type. Ce n'est pas digne d'une méthode et ce n'est pas intéressant pour les autres classes, donc c'est une propriété privée.

23voto

Greg Beech Points 55270

L'initialisation paresseuse est un endroit où ils peuvent être utiles, par exemple.

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);

private MyType MyType { get { return this.mytype.Value; } }

// In C#6, you replace the last line with: private MyType MyType => myType.Value;

Ensuite, vous pourrez écrire : this.MyType partout plutôt que this.mytype.Value et encapsuler le fait qu'il est instancié paresseusement en un seul endroit.

Il est dommage que le C# ne permette pas d'associer le champ d'appui à la propriété (c'est-à-dire de le déclarer dans la définition de la propriété) afin de le masquer complètement et de s'assurer qu'il n'est accessible que via la propriété.

2 votes

Je suis d'accord pour qu'il y ait l'aspect du scoping.

6 votes

J'utilise fréquemment cette même technique et j'ai également souhaité qu'un champ puisse avoir une portée sur un corps de code. C'est une fonctionnalité intéressante mais peu prioritaire.

5 votes

@Eric Lippert - field-declaration dans le cadre de accessor-declarations est depuis longtemps le numéro 1 de ma liste de souhaits en matière de C#. Si vous parvenez à le concevoir et à le mettre en œuvre dans une future version (réelle), je vous préparerai un gâteau.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X