comprendre les particuliers

Je ne comprends pas la nécessité d’avoir des particuliers qui ont commencé avec C # 2.

Avoir une méthode setter pour moi permet à l’utilisateur de définir des variables dans cette classe. Ce faisant, nous n’exposons pas les variables directement aux utilisateurs. Au lieu de cela, nous les laissons le faire grâce à cette méthode de réglage public.

Ceci pour moi utilise “encapsulation”. Il existe quelques arguments qui prétendent que les particuliers vont vous permettre d’appliquer l’encapsulation.

Est-ce que je n’utilise pas l’encapsulation en utilisant des méthodes de réglage publiques? Pourquoi avons-nous besoin de particuliers?

Quelle est la différence entre une classe immuable et une classe avec des particuliers?

Logiquement.

La présence d’un setter privé est due au fait que vous pouvez utiliser la propriété auto:

 public int MyProperty { get; set; } 

Que feriez-vous si vous voulez le faire en lecture seule?

 public int MyProperty { get; } 

Oh merde !! Je ne peux pas y accéder depuis ma propre classe; Je devrais le créer comme une propriété normale:

 private int myProperty; public int MyProperty { get { return myProperty; } } 

Hmm … mais j’ai perdu la fonctionnalité “Auto Property” …

 public int MyProperty { get; private set; } 

AHHH .. c’est mieux !!

Un setter privé est utile si vous avez une propriété en lecture seule et que vous ne voulez pas déclarer explicitement la variable de sauvegarde.

Alors:

 public int MyProperty { get; private set; } 

est le même que:

 private int myProperty; public int MyProperty { get { return myProperty; } } 

Pour les propriétés non implémentées automatiquement, vous disposez d’un moyen cohérent de définir la propriété à partir de votre classe, de sorte que si vous avez besoin d’une validation, etc., vous ne disposez que d’un seul emplacement.

Pour répondre à votre dernière question, le MSDN a ceci à dire sur les particuliers:

Cependant, pour les petites classes ou les structures qui encapsulent simplement un ensemble de valeurs (data) et ont peu ou pas de comportements, il est recommandé de rendre les objects immuables en déclarant l’accesseur set comme privé.

Depuis la page MSDN sur les propriétés Auto-implémentées

C’est plutôt simple. Les parameters privés vous permettent de créer des propriétés publiques ou protégées en lecture seule.

C’est tout. C’est la seule raison.

Oui, vous pouvez créer une propriété en lecture seule en spécifiant uniquement le getter, mais avec les propriétés implémentées automatiquement, vous devez spécifier à la fois get et set. Par conséquent, si vous souhaitez qu’une propriété implémentée automatiquement soit en lecture seule, vous devez utiliser particuliers. Il n’y a pas d’autre moyen de le faire.

Il est vrai que les parameters privés n’ont pas été créés spécifiquement pour les propriétés en lecture seule auto-implémentées, mais leur utilisation est un peu plus ésotérique pour d’autres raisons, centrées principalement sur les propriétés en lecture seule et la reflection et la sérialisation.

Avec l’introduction de C # 6.0 et la syntaxe des auto-initialiseurs de propriétés , les parameters privés ne sont plus nécessaires pour les propriétés définies uniquement lors de l’initialisation, en ligne ou dans le constructeur.

Ces nouvelles syntaxes comstacknt maintenant:

Propriété initialisée en ligne

 public class MyClass1 { public ssortingng MyProperty { get; } = "Aloha!" } 

Propriété initialisée par constructeur

 public class MyClass2 { public ssortingng MyProperty { get; } public MyClass2(ssortingng myProperty) { MyProperty = myProperty; } } 

Je ne comprends pas la nécessité d’avoir des particuliers qui ont commencé avec C # 2.

Par exemple, la classe de facture permet à l’utilisateur d’append ou de supprimer des éléments de la propriété Items, mais ne permet pas à l’utilisateur de modifier la référence Items (l’utilisateur ne peut pas affecter de propriété Items à une autre instance d’object de liste d’éléments).

 public class Item { public ssortingng item_code; public int qty; public Item(ssortingng i, int q) { this.item_code = i; this.qty = q; } } public class Invoice { public List Items { get; private set; } public Invoice() { this.Items = new List(); } } public class TestInvoice { public void Test() { Invoice inv = new Invoice(); inv.Items.Add(new Item("apple", 10)); List my_items = new List(); my_items.Add(new Item("apple", 10)); inv.Items = my_items; // compilation error here. } } 

Dites par exemple, vous ne stockez pas la variable réelle à travers la propriété ou utilisez la valeur pour calculer quelque chose.

Dans ce cas, vous pouvez soit créer une méthode pour faire votre calcul

 private void Calculate(int value) { //... } 

Ou vous pouvez le faire en utilisant

 public int MyProperty {get; private set;} 

Dans ces cas, je recommanderais d’utiliser le dernier, en tant que propriétés refactoriser chaque élément membre intact.

En dehors de cela, si même vous dites que vous mappez la propriété avec une variable. Dans un tel cas, dans votre code, vous voulez écrire comme ceci:

 public int myprop; public int MyProperty {get { return myprop;}} ... ... this.myprop = 30; ... ... if(this.MyProperty > 5) this.myprop = 40; 

Le code ci-dessus semble horrible car le programmeur doit toujours faire attention à utiliser MyProperty pour Get et myprop pour Set.

Pour plus de cohérence, vous pouvez utiliser un setter privé qui rend la propriété en lecture seule en dehors, tandis que vous pouvez utiliser son setter dans votre code.

Je pense que quelques personnes ont dansé autour de cela, mais pour moi, la valeur des parameters privés est que vous pouvez encapsuler le comportement d’une propriété, même au sein d’une classe. Comme l’a noté abhishek, si vous voulez déclencher un événement de modification de propriété chaque fois qu’une propriété change, mais que vous ne voulez pas qu’une propriété soit en lecture / écriture au public, vous devez soit utiliser un setter privé, soit événement où que vous modifiez le champ de sauvegarde. Ce dernier est sujet aux erreurs car vous pourriez oublier. De même, si la mise à jour d’une valeur de propriété entraîne l’exécution d’un calcul ou la modification d’un autre champ, ou une initialisation paresseuse de quelque chose, vous devrez également l’enregistrer dans le setter privé plutôt que de vous rappeler de le faire utilisation du champ support.

L’encapsulation signifie que l’état d’un object ne se produit que via une interface définie et que, de ce fait, la classe peut s’assurer que cet état est toujours valide et conforme à l’objective de la classe.

Dans certains cas, il est donc parfaitement conforme au principe de l’encapsulation de simplement exposer un champ publiquement – toutes les valeurs possibles pour le champ sont valables avec toutes les autres valeurs possibles de tous les autres champs, et donc le programmeur peut activement décider d’autoriser le champ être manipulé librement par code extérieur.

Ces cas sont pour la plupart limités aux classes qui sont principalement des “anciennes données”. Ils ne sont pas non plus très intéressants à cet égard, assez sur eux.

Dans d’autres cas, dans d’autres langages, on aurait une méthode getter et setter, quelque chose comme int getId() pour obtenir une valeur et void setId(int val) pour le mettre à jour.

Les propriétés nous permettent d’utiliser la même syntaxe pour lire et écrire à l’aide de méthodes telles que celles utilisées pour lire et écrire un champ. C’est un bon sucre syntaxique, mais pas indispensable.

(En fait, en raison de la façon dont la reflection fonctionne et des cas tels que DataBinder.Eval il peut être utile d’avoir une propriété même si un champ fonctionne correctement, mais c’est une autre affaire).

Jusqu’à ce que des parameters privés soient introduits (en fait, ce qui a changé avec C # 2 est la syntaxe pour avoir un setter privé et un getter public ou protégé dans le même bloc), nous pourrions avoir une méthode privée pour faire le travail du setter privé, les particuliers ne sont pas vraiment nécessaires. Ils sont cependant pratiques, alors que le sucre syntaxique est très utile.

L’encapsulation n’est pas une question de savoir si vos créateurs (ou vos getters) sont publics, privés, protégés ou internes, mais s’ils sont appropriés . Commencez avec une valeur par défaut pour chaque champ étant privé (et en readonly ), puis ajoutez si nécessaire des membres (qu’il s’agisse de propriétés ou de méthodes) qui modifient ces champs et assurez-vous que l’object rest valide à mesure qu’il change . Cela garantit que l’ invariant d’ une classe est conservé, ce qui signifie que les règles décrivant l’ensemble des états valides dans lesquels il peut se trouver ne sont jamais rompues (les constructeurs aident également en s’assurant qu’il démarre dans un état aussi valide).

En ce qui concerne votre dernière question, être immuable signifie qu’une classe n’a pas de paramètre public, protégé ou interne, ni de méthodes publiques, protégées ou internes qui modifient des champs. Il y a des degrés de ceci, en C # il y a trois degrés possibles:

  1. Tous les champs d’instance d’une classe sont en readonly , donc même le code privé ne peut pas le modifier. Il est garanti qu’il soit immuable (tout ce qui essaie de le modifier ne se comstackra pas) et que des optimisations peuvent être faites à l’arrière.

  2. Une classe est immuable de l’extérieur car aucun membre public ne change quoi que ce soit, mais n’est pas garanti par l’utilisation de readonly pour ne pas être modifié depuis l’intérieur.

  3. Une classe est immuable, vue de l’extérieur, même si certains états sont des changements dans l’implémentation. Par exemple, un champ peut être mémorisé et, par conséquent, alors que de l’extérieur, une tentative de l’obtenir récupère simplement la même valeur, la première tentative de ce type la calcule et la stocke ensuite pour une tentative ultérieure.

Oui, vous utilisez l’encapsulation en utilisant des propriétés, mais l’encapsulation comporte plus de nuances que la simple prise de contrôle de la lecture et de l’écriture des propriétés. Refuser une propriété à définir en dehors de la classe peut être utile à la fois pour la robustesse et les performances.

Une classe immuable est une classe qui ne change pas une fois créée, de sorte que les créateurs privés (ou pas du tout) sont nécessaires pour protéger les propriétés.

Les installateurs privés sont devenus plus fréquents avec le raccourci de propriété qui a été créé dans C # 3. Dans C # 2, le setter était souvent omis et les données privées étaient directement accessibles quand elles étaient définies.

Cette propriété:

 public int Size { get; private set; } 

est le même que:

 private int _size; public int Size { get { return _size; } private set { _size = value; } } 

sauf que le nom de la variable de sauvegarde est créé en interne par le compilateur, vous ne pouvez donc pas y accéder directement.

Avec la propriété abrégée, le setter privé est nécessaire pour créer une propriété en lecture seule, car vous ne pouvez pas accéder directement à la variable de sauvegarde.

Je ne comprends pas la nécessité d’avoir des particuliers qui ont commencé avec C # 2.

Exemple d’utilisation:

J’ai une instance d’un object d’application 'UserInfo' qui contient une propriété SessionTokenIDV1 que je ne souhaite pas exposer aux consommateurs de ma classe.

J’ai également besoin de pouvoir définir cette valeur dans ma classe.

Ma solution consistait à encapsuler la propriété comme indiqué et à rendre le setter privé afin que je puisse définir la valeur du jeton de session sans permettre au code d’instanciation de le définir (ou même de le voir dans mon cas).

 public class UserInfo { public Ssortingng SessionTokenIDV1 { get; set; } } public class Example { // Private vars private UserInfo _userInfo = new UserInfo(); public ssortingng SessionValidV1 { get { return ((_userInfo.SessionTokenIDV1 != null) && (_userInfo.SessionTokenIDV1.Length > 0)) ? "set" : "unset"; } private set { _userInfo.SessionTokenIDV1 = value; } } } 

Edit: Modification de la balise de code fixe: l’exemple comportait des erreurs corrigées

Vous avez besoin d’un setter privé, si vous souhaitez prendre en charge le scénario suivant (pas seulement pour cela, mais cela devrait vous indiquer une bonne raison): Vous avez une propriété en lecture seule dans votre classe, c.-à-d. cela, mais cela peut changer après la construction de l’instance. Pour les liaisons, vous devez alors déclencher un événement PropertyChanged, de préférence dans le configurateur de propriété (privé). En fait, vous pouvez simplement déclencher l’événement PropertyChanged depuis un autre endroit de la classe, mais utiliser le setter privé pour cela est une “bonne citoyenneté”, car vous ne dissortingbuez pas vos sortingggers de propriété tout au long de votre classe. propriété, où il appartient.