I’m not sure what this is called, or where I did see this, so I don’t really know what to search for. Therefore I’m trying to explain what I mean.
Suppose I have the following class structure, where TypeB
is used within TypeA
:
class TypeA
{
public TypeB B
{ get; set }
}
class TypeB
{
public int X
{ get; set }
}
Now when I have an instance of TypeA, I want to disallow, that I can directly modify the values of TypeB without reassigning. So basically I want to prevent this:
TypeA a = new TypeA();
// this should not be possible:
a.B.X = 1234;
// but this should work:
TypeB b = a.B;
b.X = 1234;
a.B = b;
The reason is that I am persisting the object in a special way, so to keep track of changes in TypeB
correctly, I want to require that the value of B
within TypeA
is reassigned.
I think that I have seen a similar thing before with some built-in object, where this threw an error and compile time. What is this called, and how can I achieve it in my custom types?
You can return a copy of the TypeB
object from the property getter in TypeA
:
class TypeA
{
private TypeB _b;
public TypeB B
{
get { return (TypeB)_b.Clone(); }
set { _b = value; }
}
}
This will prevent modifying the properties of _b directly. However, it won't actually disallow to do a.B.X = 1234;
, but the instruction will have no effect (it will only modify a copy that will immediately be discarded).
Unless TypeB
is a struct, there is no way to prevent such an instruction:
it can't be detected at runtime either, because you can't tell the difference between:
TypeB b = a.B;
b.X = 1234;
and
a.B.X = 1234;
In both cases the property is called the same way, and there is no way to know what the calling code is doing with the result...
In WPF/Silverlight there are two concepts of having "sealed" and "frozen" objects. Basically, once sealed/frozen, the object cannot be changed. You may be able to apply the same logic here:
public class SealableObject {
public bool IsSealed { get; private set; }
public void Seal() {
if (this.IsSealed)
throw new InvalidOperationException("The object is already sealed");
this.IsSealed = true;
}
protected void VerifyNotSealed() {
if (this.IsSealed)
throw new InvalidOperationException("Object is sealed");
}
}
Then you would need to check IsSealed
in your derived class TypeB
, like so:
class TypeB : SealableObject
{
private int x;
public int X
{
get { return this.x; }
set {
this.VerifyNotSealed();
this.x = value;
}
}
And then you'd need to seal TypeB when it is assigned to your TypeA property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With