An interesting paper to read regarding a similar subject is Uniqueness and Reference Immutability for Safe Parallelism by Joe Duffy et al of Microsoft Research.
Extended version of above paper:
I've only looked briefly at the paper, but it seems to capture a major concept I've been irked about for a long time. The majority of reference-type variables exist not for the purpose of identifying an object, but rather for the purpose of encapsulating the
object identified thereby; this requires that all use of the variable must obey one of two rules, but there is no convention to indicate
of the rules the variable is supposed to follow.
For a variable to usefully encapsulate a value, it is necessary that the only the owner of the variable be able to change the value encapsulated therein. This can be achieved either by
- Ensuring that the object identified by the variable is never changed by anyone, or
- Ensuring that the object is owned exclusively by the owner of the variable, and no outside references will be used in any ways the owner does not expect.
Some types which hold arrays adhere to the first pattern; others adhere to the second. Unfortunately, there is nothing in the type system--or even in field naming conventions--which would distinguish between the two usages.
If an object has an field
which encapsulates the sequence
and it wishes for that field to encapuslate
, there are two ways that could be accomplished:
arr = 2;
var temp = (int)arr.Clone();
temp = 2;
arr = temp;
Which approach is correct would depend upon which of the above rules is being followed.
I would posit that if there were a means by which variables and generic-type arguments
could specify what sort of semantics the references contained therein were supposed to have, then issues of "deep cloning" versus "shallow cloning"
would largely evaporate (if an object has a field which encapsulates an unsharable value, the corresponding field in a proper clone should identify a clone of that value; if a field encapsulates an immutable value or identifies a sharable entity, the corresponding
clone in a proper clone should identify the same object; if a field identifies an unsharable entity, then unless "manual" cloning code can resolve the situation, the containing object is unclonable.
BTW, equality testing could also be handled largely automatically if virtual methods existed to test definitions of equivalence:
1. Two objects are equivalent if there is nothing that any other object could do to make them not equivalent.
2. Two objects are value-equal if the only way they could become not value-equal would be if code that holds a reference to them changes them.
Much of the murkiness around
is a result of the fact that each definition of equivalence is useful in different cases; I believe that if objects could test them separately, 99% of ambiguity would be eliminated.
How do those concepts sound?