Pourquoi jamais utiliser des champs au lieu de propriétés?

Je suis assez nouveau en C # et je pense que les propriétés sont une chose merveilleuse. Tellement merveilleux, en fait, que je ne vois aucun avantage réel à utiliser des champs à la place. Même pour les domaines privés, il semble que la flexibilité et la modularité offertes par les propriétés peuvent au mieux vous éviter de graves maux de tête et, au pire, n’ont aucun effet.

Le seul avantage que je peux voir pour les champs est que vous pouvez les initialiser en ligne. Mais la plupart du temps, vous voulez quand même les initialiser dans le constructeur. Si vous n’utilisez pas l’initialisation en ligne, y a-t-il une raison de ne pas utiliser les propriétés tout le temps?

Modifier: Certaines personnes ont évoqué la nécessité de sauvegarder les propriétés avec des champs (explicitement ou automatiquement). Permettez-moi de clarifier ma question: y a-t-il une raison d’utiliser des champs sauf pour sauvegarder des propriétés ? Par exemple, y a-t-il un moment où SomeType someField; est préférable à SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } ?

Edit 2: DanM, Skurmedel et Seth ont tous donné des réponses très utiles. J’ai accepté les DanM, car c’est le plus complet, mais si quelqu’un résumait ses réponses en une seule réponse, je serais heureux de l’accepter.

En règle générale, les propriétés nécessitent un champ de sauvegarde, sauf s’il s’agit de simples propriétés “getter / setter”.

Donc, si vous faites juste …

 public ssortingng Name { get; set; } // automatic property 

… tu n’as pas besoin d’un terrain, et je suis d’accord, pas de raison d’en avoir un.

Cependant, si vous faites …

 public ssortingng Name { get { return _name; } set { if (value = _name) return; _name = value; OnPropertyChange("Name"); } } 

… vous avez besoin de ce champ de nom _name .

Pour les variables privées qui ne nécessitent pas de logique get / set spéciale, il s’agit en fait de décider si une propriété automatique privée ou juste un champ est nécessaire. Je fais habituellement un champ, puis, si j’ai besoin qu’il soit protected ou public , je le changerai en propriété automatique.

Mettre à jour

Comme l’a noté Yassir, si vous utilisez des propriétés automatiques, il rest encore un champ caché dans les coulisses. Ce n’est tout simplement pas quelque chose que vous devez taper. En résumé, les propriétés ne stockent pas de données, elles leur donnent access. Les champs sont ce que contiennent réellement les données. Donc, vous en avez besoin même si vous ne pouvez pas les voir.

Mise à jour 2

Concernant votre question révisée …

y a-t-il un moment où SomeType someField; est préférable à SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } ?

… une chose qui me vient à l’esprit: si vous avez un champ privé et que vous l’appelez _name (conformément à la convention pour les champs privés), cela indique à vous et à quiconque qui lit votre code que vous travaillez directement avec des données privées. Si, au contraire, vous faites de tout une propriété, et (conformément à la convention relative aux propriétés), appelez votre propriété privée Name , vous ne pouvez plus vous contenter de regarder la variable et de dire qu’il s’agit de données privées. Ainsi, utiliser uniquement les propriétés supprime certaines informations. Je n’ai pas essayé de travailler avec toutes les propriétés pour déterminer s’il s’agit d’informations cruciales, mais quelque chose est définitivement perdu.

Une autre chose, plus mineure, est public ssortingng Name { get; set; } public ssortingng Name { get; set; } public ssortingng Name { get; set; } nécessite plus de frappe (et est un peu plus compliqué) que private ssortingng _name .

Les propriétés sont une chose merveilleuse – mais il y a des frais généraux associés à l’access aux propriétés. Pas nécessairement un problème, mais une chose à prendre en compte.

Éviter la surutilisation des accesseurs et des régleurs de propriété

La plupart des gens ne se rendent pas compte que les accesseurs et les installateurs de propriétés sont similaires aux méthodes utilisées pour les frais généraux; c’est principalement la syntaxe qui les différencie. Un getter ou un setter de propriété non virtuel qui ne contient aucune instruction autre que l’access au champ sera inséré par le compilateur, mais dans de nombreux autres cas, cela n’est pas possible. Vous devriez examiner attentivement votre utilisation des propriétés; À partir d’une classe, accédez directement aux champs (si possible) et n’appelez jamais à l’aveuglette à répétition des propriétés sans stocker la valeur dans une variable. Cela dit, cela ne signifie pas que vous devriez utiliser des champs publics!

Source: http://dotnet.sys-con.com/node/46342

Si vous voulez avoir quelque chose en readonly vous devez utiliser un champ car il n’ya aucun moyen de demander à une propriété automatique de générer un champ en lecture seule.

Je le fais assez souvent.

Exemple élaboré:

 class Rectangle { private readonly int _width; private readonly int _height; public Rectangle(int width, int height) { _width = width; _height = height; } public int Width { get { return _width; } } public int Height { get { return _height; } } } 

Cela signifie que rien dans Rectangle ne peut modifier la largeur ou la hauteur après la construction. Si on essaie au compilateur de se plaindre.

Si j’avais utilisé une propriété automatique avec un installateur privé, le compilateur ne me protégerait pas.

Une autre raison que je vois est que si un élément de données n’a pas besoin d’être exposé (restr private ), pourquoi en faire une propriété?

Essayez simplement d’utiliser une propriété lorsque vous utilisez les arguments ref / out:

 someObject.SomeMethod(ref otherObject.SomeProperty); 

Ça ne comstackra pas.

Je ne vois pas pourquoi vous utiliseriez des propriétés privées. Quel avantage y at-il à

 private int Count {get; set;} 

plus de

 private int count 

Bien que je sois d’accord avec ce que je perçois comme “l’intention” dans la déclaration de David Basarab: “Il n’y a aucune raison d’exposer publiquement des champs”, je voudrais append une emphase légèrement différente:

Je modifierais la citation de David ci-dessus comme suit: “Il n’ya aucune raison d’exposer publiquement des champs … en dehors de la classe … sauf par le choix délibéré d’encapsuler les champs dans des propriétés à travers lesquels l’access est contrôlé de manière rigoureuse.

Les propriétés ne sont pas simplement un “vernis” de syntaxe sur des champs “ajoutées à” C #: elles constituent une fonctionnalité fondamentale du langage conçue pour de bonnes raisons, notamment:

  1. contrôler ce qui est exposé et non exposé en dehors des classes (encapsulation, masquage de données)

  2. permettant à certaines actions d’être exécutées lorsqu’une propriété est accédée ou définie: actions qui sont mieux exprimées dans la propriété ‘get et’ définie, plutôt que d’être “élevées” en méthodes définies en externe.

  3. Les interfaces par conception ne peuvent pas définir de champs, mais peuvent définir des propriétés.

Une bonne conception OO signifie faire des choix conscients au sujet de “l’état”:

  1. champs de variable locale: quel état est privé à une méthode et transitoire : les variables locales ne sont généralement valides que dans le cadre d’un corps de méthode, ou même avec une “durée de vie aussi étroite” que dans le cadre de quelque chose comme une boucle for. Bien entendu, vous pouvez également considérer les variables de paramètre d’une méthode comme “locales”.

  2. Champs d’instance de classe: quel état est privé à une classe et a une existence indépendante pour chaque instance d’une classe, mais doit probablement être utilisé à plusieurs endroits dans la classe.

  3. champs d’instances statiques: quel état sera une propriété de la classe uniquement, indépendamment du nombre d’instances de la classe.

  4. Etat délibérément et consciemment exposé “en dehors” de la classe: l’idée principale étant qu’il existe au moins un niveau d’indirection interposé entre la classe et les “consommateurs” des données exposées par la classe. Le “revers” de “l’exposition” est bien entendu l’intention délibérée de cacher (encapsuler, isoler) un code de mise en oeuvre.

    une. via des biens publics: tous les aspects de cette question sont bien couverts dans toutes les autres réponses ici

    b. via des indexeurs

    c. via des méthodes

    ré. Les variables statiques publiques se trouvent généralement dans les classes utilitaires, qui sont souvent des classes statiques.

Suggérez votre avis: MSDN sur ‘Champs … MSDN sur Propriétés … MSDN sur Indexeurs

Il n’y a aucune raison d’exposer publiquement les champs.

Si vous exposez publiquement un champ, vous ne pouvez pas modifier la source des informations, de la définition en ligne au fichier de configuration, sans refactoring. \

Vous pouvez utiliser un champ pour masquer les données internes. Je préfère rarement cela, je n’utilise des champs que lorsque je fais quelque chose à cacher publiquement et que je l’utilise dans une propriété. (ie je n’utilise pas la génération automatique de propriété)

Les champs sont le seul endroit où vous pouvez stocker l’état. Les propriétés ne sont en réalité qu’une paire de méthodes avec une syntaxe spéciale qui leur permet d’être mappées à la méthode get ou set en fonction de leur utilisation: si une propriété modifie ou accède à un état, cet état doit toujours être stocké dans un champ. .

Vous ne voyez pas toujours les champs. Avec les propriétés automatiques C # 3, le champ est créé pour vous par le compilateur. Mais c’est toujours là. De plus, les propriétés automatiques ont des limitations importantes (par exemple, pas de prise en charge INotifyPropertyChanged, pas de logique métier dans les parameters), ce qui signifie qu’elles sont souvent inappropriées, et vous devez quand même créer un champ explicite et une propriété définie manuellement.

Selon la réponse de David , vous avez raison si vous parlez d’une API: vous ne voulez presque jamais intégrer l’état interne (champs) à l’API.

La syntaxe des champs est beaucoup plus rapide à écrire que celle des propriétés. Par conséquent, lorsqu’il est prudent d’utiliser un champ (privé de la classe), pourquoi ne pas l’utiliser et enregistrer ce type de saisie supplémentaire? Si les propriétés implémentées automatiquement avaient la syntaxe concise courte et agréable et que vous deviez effectuer un travail supplémentaire pour créer un ancien champ simple, les utilisateurs pourraient simplement commencer à utiliser les propriétés. En outre, c’est une convention maintenant en C #. C’est ce que les gens pensent et c’est ce qu’ils s’attendent à voir dans le code. Si vous faites quelque chose de différent de la normale, vous allez confondre tout le monde.

Mais vous pouvez vous demander pourquoi la syntaxe des champs ne crée pas une propriété implémentée automatiquement au lieu d’un champ, de sorte que vous obtenez le meilleur des deux mondes: des propriétés partout et une syntaxe concise.

Il y a une raison très simple pour laquelle nous avons toujours besoin de champs explicites:

C # 1.0 ne possédait pas toutes ces fonctionnalités intéressantes que nous avons maintenant, donc les champs étaient une réalité de la vie – on ne pourrait pas vraiment vivre sans eux. Beaucoup de code repose sur des champs et des propriétés qui sont visiblement différents. Il ne peut tout simplement pas être changé maintenant sans casser des tonnes de code.

Je soupçonne également qu’il y a des conséquences sur les performances, mais peut-être que cela peut être résolu par la gigue.

Nous sums donc coincés avec les champs pour toujours, et comme ils sont là et qu’ils ont pris la meilleure syntaxe, il est logique de les utiliser quand il est sécuritaire de le faire.

Les champs et les propriétés ne sont pas interchangeables. Je suppose que ce que vous dites, c’est accéder à des champs privés à travers des propriétés privées. Je fais cela quand cela a du sens, mais pour la plupart, ce n’est pas nécessaire. L’optimiseur JIT aura toujours access à un champ privé via une propriété privée dans la plupart des cas. Et encapsuler un champ privé dans une propriété privée n’est de toute façon pas considéré comme un changement radical, car les membres privés ne font pas partie de votre interface.

Personnellement, je n’exposerais jamais aucun champ d’instance protégé / public. Il est généralement acceptable d’exposer un champ statique public avec un modificateur en lecture seule tant que le type de champ est lui-même immuable. Cela se voit souvent avec les champs statiques SomeStruct.Empty.

Comme d’autres l’ont noté, vous aurez de toute façon besoin d’un champ de sauvegarde privé pour les propriétés.

L’utilisation des champs sur les propriétés présente également un avantage en termes de rapidité. Dans 99,99% des cas, ce n’est pas grave. Mais dans certains cas, cela pourrait.

La vitesse. Si un champ est défini ou lit des milliards de fois au cours d’une simulation, vous souhaitez utiliser un champ et non une propriété pour éviter la surcharge d’un appel de sous-routine. Conformément à OO (DDD?) Autant que possible, dans ce cas, je vous conseillerais de ne recourir aux champs que dans une classe dédiée à la représentation d’une sorte de “valeur” comme une personne. La logique doit être réduite au minimum. Au lieu de cela, avoir un créateur de personne ou un préposé au personnel.

Mais si vous avez ces problèmes, alors vous ne programmez probablement pas c ++ ni c #, n’est-ce pas?

Il y a plusieurs bonnes réponses (partielles) de @Seth (les champs fonctionnent mieux, donc dans un contexte privé, vous pouvez aussi bien les utiliser à votre avantage quand cela fait sens), @Skurmedel (les champs peuvent être en lecture seule), @Jenk (les champs peuvent être utilisé pour réf / out). Mais j’aimerais en append un de plus:

Vous pouvez utiliser la syntaxe d’initialisation simplifiée pour définir la valeur d’un champ, mais pas une propriété. c’est à dire:

 private int x = 7; 

contre

 private int x { get; set; } // This must go in the constructor, sometimes forcing you to create // a constructor that has no other purpose. x = 7;