On nous dit souvent que nous devrions protéger l’encapsulation en faisant des méthodes getter et setter (propriétés en C #) pour les champs de classe, au lieu de les exposer au monde extérieur.
Mais il arrive souvent qu'un champ ne soit là que pour contenir une valeur et ne nécessite aucun calcul pour être obtenu ou défini. Pour ceux-ci nous ferions tous ce numéro:
public class Book
{
private string _title;
public string Title
{
get{ return _title; }
set{ _title = value; }
}
}
Eh bien, j'ai une confession, je ne pouvais pas supporter d'écrire tout ça (vraiment, ce n'était pas obligé de l'écrire, c'était de le regarder), alors je me suis mis à l'écart et j'ai utilisé des champs publics.
Vient ensuite C # 3.0 et je vois qu'ils ont ajouté des propriétés automatiques:
public class Book
{
public string Title {get; set;}
}
ce qui est plus ordonné, et je suis reconnaissant pour cela, mais vraiment, qu'est-ce qui est si différent de simplement créer un terrain public?
public class Book
{
public string Title;
}
Dans une question connexe il y a quelque temps, il y avait un lien vers une publication sur le blog de Jeff, expliquant certaines différences.
Propriétés vs variables publiques
Changer une variable en une propriété est un changement radical. Par exemple:
TryGetTitle(out book.Title); // requires a variable
En ignorant les problèmes liés à l'API, le débogage est ce que je trouve le plus précieux pour utiliser une propriété.
Le débogueur CLR ne prend pas en charge les points de rupture de données (la plupart des débogueurs natifs le font). Par conséquent, il n'est pas possible de définir un point d'arrêt sur la lecture ou l'écriture d'un champ particulier sur une classe. Ceci est très limitant dans certains scénarios de débogage.
Les propriétés étant implémentées comme des méthodes très minces, il est possible de définir des points d'arrêt sur la lecture et l'écriture de leurs valeurs. Cela leur donne une longueur d'avance sur les champs.
Le passage d’un champ à une propriété rompt le contrat (par exemple, tout le code de référencement doit être recompilé). Ainsi, lorsque vous avez un point d’interaction avec d’autres classes - tout membre public (et généralement protégé), vous souhaitez planifier votre croissance future. Faites-le en utilisant toujours les propriétés.
Cela ne fait rien aujourd'hui d'en faire une auto-propriété. Trois mois plus tard, vous vous rendez compte que vous voulez le charger paresseux et mettez un chèque nul au getter. Si vous aviez utilisé un champ, il s'agit au mieux d'une modification de recompilation et, au pire, d'une modification impossible, selon qui et quoi d'autre repose sur vos assemblées.
Tout simplement parce que personne n'en a parlé: vous ne pouvez pas définir de champs sur les interfaces. Donc, si vous devez implémenter une interface spécifique qui définit les propriétés, les propriétés automatiques sont parfois une fonctionnalité vraiment intéressante.
Une différence énorme qui est souvent négligée et qui n'est mentionnée dans aucune autre réponse: écrasante. Vous pouvez déclarer des propriétés virtuelles et les remplacer alors que vous ne pouvez pas faire la même chose pour les champs membres publics.
Un autre avantage des propriétés implémentées automatiquement par rapport aux champs publics est que vous pouvez rendre les accesseurs d'ensembles privés ou protégés, en fournissant à la classe d'objets où il a été défini un contrôle supérieur à celui des champs publics.
Il n'y a rien de mal à créer un champ public
. Mais souvenez-vous de créer getter/setter
avec private
les champs n’est pas une encapsulation. IMO, Si vous ne vous souciez pas des autres fonctionnalités d'un Property
, vous pouvez aussi bien le rendre public
.
Tout est une question de version et de stabilité des API. Il n'y a pas de différence dans la version 1 - mais plus tard, si vous décidez que vous devez en faire une propriété avec un certain type d'erreur lors de la vérification des erreurs dans la version 2, vous n'avez pas besoin de modifier votre API. Aucune modification de code, nulle part, à l'exception de la définition de la propriété.
Si vous décidez ultérieurement de vérifier que le titre est unique, en le comparant à une collection ou à une base de données, vous pouvez le faire dans la propriété sans modifier le code qui en dépend.
Si vous utilisez uniquement un attribut public, vous aurez moins de flexibilité.
La flexibilité supplémentaire sans rompre le contrat est ce qui est le plus important pour moi en ce qui concerne l'utilisation de propriétés. Jusqu'à ce que j'aie besoin de cette flexibilité, la génération automatique a tout son sens.
Une chose que je trouve très utile, ainsi que tous les codes et toutes les raisons de tester, est que s'il s'agit d'une propriété par rapport à un champ, Visual Studio IDE vous montre les références d'une propriété, mais pas une champ.