L'immuabilité est encore un domaine où C# est à maturité. Jusqu'à présent, C# n'a pas adopté l' const
de la sémantique de C++ ... ce qui je pense est une bonne chose. Le comportement de l' const
en C++ souvent fait qu'il est difficile de concevoir les hiérarchies de classe qui a travaillé de la façon que vous le vouliez. Il n'était pas rare de voir le code parsemé d' const_cast<>
de contourner constness où il n'était pas souhaitable. Heureusement, les concepteurs de C# inventer une simple mais toujours expressif alternative.
À l'heure actuelle, il n'existe pas de fonctionnalité de langage qui marque les paramètres ou les objets passés à des méthodes comme immuable. Le meilleur que vous pouvez faire est de passer d'un objet à l'aide d'une interface (ou mieux encore un wrapper) qui ne permet les opérations de lecture.
Pour certains de la norme collection .NET, vous pouvez utiliser l' ReadOnlyCollection
wrapper, qui englobait tout mutable ICollection
type au sein d'une lecture seule contenant.
La création d'immuable types exige de la planification et de prise de conscience des fonctionnalités de langage. Par exemple, l' readonly
mot-clé est votre ami. Il vous permet de déclarer des membres d'une classe ou structure comme immuable. Malheureusement, cette immutabilité ne s'applique qu'à la référence, et non les membres de l'objet référencé. Ce que cela signifie est que vous pouvez déclarer:
private readonly int[] m_Values = new int[100];
public void SomeMethod()
{
m_Values = new int[50]; // illegal, won't compile!
m_Values[10] = 42; // perfectly legal, yet undesirable
}
Dans l'exemple ci-dessus, la référence à la matrice est immuable, mais les différents éléments du tableau ne sont pas. Ce problème s'étend au-delà des tableaux, bien sûr.
Une pratique que j'ai trouvé utile lors de la conception immuable types, est de séparer l'immuable comportement dans sa propre interface qui est ensuite mis en œuvre par une classe qui gère les données. L'interface n'expose les propriétés et méthodes qui sont garantis de ne pas la mutation de l'état de l'objet. Il est alors possible de passer les instances de votre type de méthodes que les paramètres de ce type d'interface. C'est une forme faible de l'immuabilité de soutien - depuis la méthode appelée peut souvent mettre la référence à la mutable type. Un mieux, mais de plus en plus lourde alternative, est de créer un wrapper de mise en œuvre qui met en œuvre la même interface et maintient une référence vers l'instance réelle (un peu comme l' ReadOnlyCollection
t). C'est plus de travail, mais offre une plus forte garantie pour l'immutabilité.
L'approche que vous choisissez dépend de la façon dont des garanties importantes de l'immuabilité et de la façon dont beaucoup de temps et d'effort que vous êtes prêt à dépenser pour y arriver.
Si vous êtes intéressés à en savoir plus sur ce sujet, Eric Lippert a une excellente série d'articles sur l'immuabilité en C#.