Quel est le meilleur entre un modificateur readonly et un setter privé?

J’ai travaillé sur la création d’une classe et soudain une pensée me vint à l’esprit quelle est la différence entre les deux codes:

public readonly ssortingng ProductLocation; 

ET

 public ssortingng ProductLocation { get; private set; } 

Pouvez-vous me donner une idée du moment pour mieux utiliser les éléments suivants? Merci.

Le premier est un champ en lecture seule, tandis que le second est compilé comme une paire de méthodes (et toutes les lectures de la propriété ProductLocation sont compilées dans les appels à la méthode get correspondante et y sont écrites pour être compilées dans les appels à la méthode set ) En interne, ces méthodes liront / écrivent dans un champ interne, généré automatiquement, non en lecture seule. Je dirais que la différence la plus importante est la sécurité des fils ! (comment? lire la suite!)

L’utilisation de base de la classe sera identique: le code des autres classes ne pourra lire que la valeur, pas la modifier. De plus, le code pour lire la valeur sera identique (par exemple, print(myInstace.ProductLocation) ; ici, vous ne pouvez pas dire comment il a été déclaré, cool, hein?)

La première différence, la plus sortingviale, est que la propriété avec setter privé permet aux instances de la même classe de modifier la valeur, tandis que dans le cas de la propriété readonly, même l’object lui-même ne pourra pas modifier la valeur.

Maintenant, pour la sécurité des fils. L’atsortingbut readonly sur le champ va changer la sémantique de la visibilité de la mémoire lorsque vous travaillez avec plusieurs threads (tout comme les champs final de Java).

Un champ en readonly peut uniquement être affecté à la déclaration ou au constructeur. La valeur atsortingbuée à un champ en readonly ne peut pas être modifiée (du moins pas de manière normale ) et il est garanti que chaque thread verra la valeur correctement initialisée après le retour du constructeur . Par conséquent, un champ en readonly est insortingnsèquement sûr pour les threads.

Pour obtenir la même sécurité des threads avec la propriété, vous devez append une synchronisation sur votre code, ce qui est source d’erreurs. Cela peut conduire à des verrous morts, à des courses de données ou à des performances réduites, selon les cas, et surtout si vous n’avez pas d’expérience.

Donc, si la valeur représente quelque chose qui ne peut pas être changé de manière sémantique après la construction de l’object, vous ne devez pas déclarer un setter privé (cela impliquerait que l’object pourrait le changer). Optez pour le champ readonly (et peut-être le déclarez privé et déclarez une propriété publique avec seulement un getter accédant au champ! Ceci est en fait la forme préférée, car il n’est pas bon d’exposer des champs, il est préférable d’exposer uniquement les méthodes) de nombreuses raisons expliquent pourquoi dans cette réponse )

En général, il n’est pas recommandé dans .NET d’exposer publiquement les champs membres, ceux-ci doivent être encapsulés par une propriété. Alors supposons que vous pourriez avoir

 private readonly ssortingng productLocation; public ssortingng ProductLocation { get { return productLocation; } } 

contre

 public ssortingng ProductLocation { get; private set; } 

Dans cette configuration, et en ignorant ce que l’on pourrait accomplir par reflection, la sémantique est que dans le premier cas, la variable productLocation ne peut être initialisée que sur place et dans le constructeur de la classe. Les autres membres de la classe ne peuvent pas modifier la valeur. Les consommateurs externes ne sont pas en mesure de définir la valeur.

Dans la deuxième version, les consommateurs externes n’ont toujours pas access à la définition de la valeur. Cependant, la classe elle-même peut modifier la valeur à tout moment. Si tout ce que vous avez est un DTO (c’est-à-dire une classe qui ne transporte que des données, il n’y a pas de logique exprimée via des méthodes), alors ce n’est pas si différent de la version en readonly . Cependant, pour les classes avec des méthodes, ces méthodes peuvent modifier la valeur derrière ProductLocation .

Si vous souhaitez appliquer le concept d’un champ immuable après la construction, utilisez readonly . Mais pour un DTO, je pourrais aller pour le private set; option, principalement parce que c’est moins le code passe-partout.

Avec l’ initialiseur de propriété automatique C # 6.0, il y a moins de méthode standard

 private readonly ssortingng productLocation; public ssortingng ProductLocation { get { return productLocation; } } 

Lequel est

 public ssortingng ProductLocation { get; } 

C’est en lecture seule. Seulement initialisé à partir du constructeur ou en ligne. Il ne peut pas être modifié après l’initialisation. (Immuable de n’importe où)

Cependant, si vous utilisez un ensemble privé

 public ssortingng ProductLocation { get; private set } 

C’est en lecture seule de l’extérieur. Mais peut être initialisé n’importe quand n’importe où dans la classe elle-même. Et peut être édité dans son cycle de vie par la classe elle-même. (Mutable de classe, immuable de l’extérieur)

Le premier (en utilisant readonly ) signifie que l’object ne peut même pas modifier la valeur de son propre champ , une fois que l’object a été instancié, et que les autres ne peuvent jamais le modifier.

Le second (utilisant private set ) signifie que l’object peut modifier la valeur de son champ après son instanciation, mais que les autres ne peuvent jamais le modifier.

Je voudrais utiliser le premier pour quelque chose que vous savez ne changera pas , et utiliser ce dernier pour quelque chose où la valeur peut changer, mais vous ne voulez pas que les autres le changent.

Le premier est un champ dont la valeur ne peut être définie qu’à l’instanciation .

La seconde est une propriété dont la valeur peut être définie à tout moment (mais uniquement par son object contenant).


Correction: La propriété peut être définie à tout moment par toute instance de la même classe (et pas seulement par son object contenant).