Can this C # class be called "immutable"?

I need to make my mutable class immutable, now it looks like this. However, nonetheless, I'm not sure that I have a completely β€œimmutable” class, and if so, what immutability is it called?

public class B<C, M> where C : IComparable<C> where M : IMetaData { internal B(char tau, M metadata, B<C, M> nextBlock) { if (tau == 'R') omega = 1; _lambda = new List<Lambda<C, M>>(); _lambda.Add(new Lambda<C, M>(tau: tau, atI: metadata)); foreach (var item in nextBlock.lambda) if (item.tau != 'L') _lambda.Add(new Lambda<C, M>(tau: 'M', atI: item.atI)); } internal int omega { private set; get; } private List<Lambda<C, M>> _lambda { set; get; } internal ReadOnlyCollection<Lambda<C, M>> lambda { get { return _lambda.AsReadOnly(); } } internal B<C, M> Update(int Omega, char tau, M metadata) { B<C, M> newBlock = new B<C, M>(); newBlock.omega = Omega; newBlock._lambda = new List<Lambda<C, M>>(this._lambda); newBlock._lambda.Add(new Lambda<C, M>(tau: tau, atI: metadata)); return newBlock; } internal B<C, M> Update(Dictionary<uint, Lambda<C, M>> lambdas) { B<C, M> newBlock = new B<C, M>(); newBlock.omega = this.omega; newBlock._lambda = new List<Lambda<C, M>>(); foreach (var l in lambdas) newBlock._lambda.Add(new Lambda<C, M>(tau: l.Value.tau, atI: l.Value.atI)); return newBlock; } } public class Lambda<C, M> where C : IComparable<C> where M : IMetaData { internal Lambda(char tau, M atI) { this.tau = tau; this.atI = atI; } internal char tau { private set; get; } internal M atI { private set; get; } } 

Based on my application, B needs to be changed from time to time; therefore, to preserve the immutability property, each update must be performed using the t Update function, which returns a brand new B

Update

To shed light on IMetaData , which was deliberately discovered by John Skeet, consider the following definitions:

 public interface IMetaData { UInt32 hashKey { set; get; } } 

and the next class is passed as M to B<C, M>

 public class MetaData : IMetaData { public UInt32 hashKey { set; get; } } 
+6
source share
2 answers

No external code can observe any mutations of this type, which is enough to be considered "unchanged" in the general expression. The only time he ever mutated was during his own constructor; it never mutates after creation, so no external object can ever observe a type mutation. This tends to apply to almost all types that are considered "immutable."

While a type has the technical ability to mutate itself outside its constructor, since it has both fields that are not readonly , as well as a mutable List , it never performs any such mutations or provides any means of mutating data.

+5
source

The vast majority of types of immutable classes achieve their immutability by encapsulating data in an object of a mutable class type, but ensuring that no reference to this object is ever exposed to code that can mutate it. Given that .NET does not have any immutable array types other than String , this approach is often the only practical way for a variable-size collection to provide efficient random access. Types that do not require efficient random access can use more "deeply immutable" means of data storage, such as linked lists or trees that store everything in readonly fields, but in practice, if there is no possible sequence of execution through which the object instance can be mutated, then this particular instance can be legitimately described as "immutable", even if its class would allow the instance to be mutated by someone with reference to it.

Regarding whether it is possible to consider a link of an interface type as an object of immutability, which will depend on whether the contract exists in the interface itself or in the means by which a link was provided that would indicate either that all legitimate implementations of this interface it will be unchanged that the particular instance identified by the link will be unchanged or (if the code containing the link never exposes it to external code) that the instance will never be exposed to code that may mutate to him. If the interface promises immutability, then the code that receives the link from external code can use it directly; otherwise, he will need to get a link from the code that promises that there will be no "unrelated" links to it. One of the possible patterns would be for the interface to offer the AsReadableSnaphot method, which would guarantee the return of an object that encapsulates the state of the object when it is called and promises that there is no external link that mutates the given object; an immutable class can implement such a method to simply return itself, while a mutable one could implement it to return the clone by itself). If class instances can be large, it may be desirable to have AsReadableSnapshot instantiate an immutable class (so that the AsReadableSnapshot call AsReadableSnapshot not make another copy of the data in it), but if they are always small, having a returned object with a mutable type, there should be no problem .

+2
source

Source: https://habr.com/ru/post/977543/


All Articles