J'ai une classe avec deux readonly int
champs. Ils sont exposés en tant que propriétés:
public class Thing
{
private readonly int _foo, _bar;
/// <summary> I AM IMMUTABLE. </summary>
public Thing(int foo, int bar)
{
_foo = foo;
_bar = bar;
}
public int Foo { get { return _foo; } set { } }
public int Bar { get { return _bar; } set { } }
}
Cependant, cela signifie que le code suivant est parfaitement légal:
Thing iThoughtThisWasMutable = new Thing(1, 42);
iThoughtThisWasMutable.Foo = 99; // <-- Poor, mistaken developer.
// He surely has bugs now. :-(
Les bogues qui découlent de l' hypothèse que cela fonctionnerait seront certainement insidieux. Bien sûr, le développeur erroné aurait dû lire les documents. Mais cela ne change pas le fait qu'aucune erreur de compilation ou d'exécution ne l'a averti du problème.
Comment Thing
changer la classe pour que les développeurs soient moins susceptibles de faire l'erreur ci-dessus?
Jetez une exception? Utilisez une méthode getter au lieu d'une propriété?
c#
object-oriented
immutability
properties
kdbanman
la source
la source
Interfaces
. Je ne suis pas sûr que c'est ce que je fais.Réponses:
Pourquoi rendre ce code légal?
Sortez le
set { }
si ça ne fait rien.Voici comment définir une propriété publique en lecture seule:
la source
public int Foo { get; }
(auto-propriété avec seulement un getter) mais l'public int Foo { get; private set; }
est.Avec C # 5 et avant, nous étions confrontés à deux options pour les champs immuables exposés via un getter:
readonly
pour détruire l'immuabilité. Cela a cependant créé beaucoup de code de plaque de chaudière.Cependant, avec C # 6 (disponible dans VS2015, qui a été publié hier), nous obtenons maintenant le meilleur des deux mondes: les propriétés automatiques en lecture seule. Cela nous permet de simplifier la classe OP pour:
Les lignes
Foo = foo
etBar = bar
ne sont valides que dans le constructeur (qui satisfait à l'exigence robuste en lecture seule) et le champ de support est implicite, plutôt que d'avoir à être explicitement défini (ce qui permet d'obtenir le code le plus simple).la source
Vous pourriez simplement vous débarrasser des colons. Ils ne font rien, ils dérouteront les utilisateurs et entraîneront des bugs. Cependant, vous pouvez plutôt les rendre privés et ainsi vous débarrasser des variables de support, simplifiant votre code:
la source
public int Foo { get; private set; }
" Cette classe n'est plus immuable car elle peut se changer. Merci quand même!readonly
mot-clé est juste un joug poka, c'est-à-dire qu'il empêche la classe de briser l'immutabilité à l'avenir; il n'est cependant pas nécessaire pour atteindre l'immuabilité.Deux solutions.
Simple:
N'incluez pas les setters comme l'a noté David pour les objets immuables en lecture seule.
Alternativement:
Permet aux setters de renvoyer un nouvel objet immuable, verbeux par rapport à l'ancien mais fournit un état dans le temps pour chaque objet initialisé. Cette conception est un outil très utile pour la sécurité et l'immuabilité des threads qui s'étend sur tous les langages OOP impératifs.
Pseudocode
usine statique publique
la source