Puisque l'immutabilité n'est pas complètement intégrée dans C# comme elle l'est dans F#, ou complètement dans le framework (BCL) malgré un certain support dans le CLR, quelle est une solution assez complète pour l'(im)mutabilité pour C# ?
Ma préférence va à une solution composée de modèles/principes généraux compatibles avec
- une seule bibliothèque open-source avec peu de dépendances
- un petit nombre de bibliothèques open-source complémentaires/compatibles
- quelque chose de commercial
que
- couvre les types d'activités de Lippert immutabilité
- offre des performances décentes (je sais que c'est vague)
- supporte la sérialisation
- prend en charge le clonage/la copie (profonde, superficielle, partielle ?)
- semble naturel dans des scénarios tels que DDD, builder patterns, configuration et threading
- fournit des collections immuables
J'aimerais également inclure des modèles que vous, en tant que communauté, pourriez proposer et qui ne s'inscrivent pas exactement dans un cadre tel que l'expression de l'intention de mutabilité par le biais d'interfaces (où les deux clients qui ne devrait pas changer quelque chose et peut vouloir modifier quelque chose ne peut se faire que par le biais d'interfaces, et non de la classe d'appui (oui, je sais que ce n'est pas une véritable immutabilité, mais c'est suffisant) :
public interface IX
{
int Y{ get; }
ReadOnlyCollection<string> Z { get; }
IMutableX Clone();
}
public interface IMutableX: IX
{
new int Y{ get; set; }
new ICollection<string> Z{ get; } // or IList<string>
}
// generally no one should get ahold of an X directly
internal class X: IMutableX
{
public int Y{ get; set; }
ICollection<string> IMutableX.Z { get { return z; } }
public ReadOnlyCollection<string> Z
{
get { return new ReadOnlyCollection<string>(z); }
}
public IMutableX Clone()
{
var c = MemberwiseClone();
c.z = new List<string>(z);
return c;
}
private IList<string> z = new List<string>();
}
// ...
public void ContriveExample(IX x)
{
if (x.Y != 3 || x.Z.Count < 10) return;
var c= x.Clone();
c.Y++;
c.Z.Clear();
c.Z.Add("Bye, off to another thread");
// ...
}