Update: This question has been revised to make it clearer. The answers below seem to reflect that this method works well. Hopefully this question can help people who need to add a get
or set
to an existing property.
Ran into a problem today where I needed to override a base class's get
-only property with both a get
and set
. Current consensus seems to be that this is impossible, but I think that I found a method.
The general idea is to make a new
property instead of directly override
ing the old one, then we create a bridge method that override
s the old get
method with a call to the new one.
Here's some code for an arbitrary pre-existing type structure that can't be modified.
public abstract class A
{
public abstract int X { get; }
}
public class B : A
{
public override int X { get { return 0; } }
}
We'd like to write this code, but it won't compile.
public class C : B // won't compile: X can't have a 'set' method
{
private int _x;
public override int X { get { return _x; } set { _x = value; } }
}
We write the code we want anyway, but we declare the property to be new
instead of override
, allowing us to declare a set
method.
public class D : C // Same thing, but will compile because X is 'new'
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } } // also 'virtual', unless we want to 'sealed' it.
// Bridge method provides the override functionality:
protected sealed override int XGetter { get { return this.X; } } // 'sealed' because this bridge should always refer to the new 'get' method
}
The extra bridge method, XGetter
, provides the override
. This is glued to the base class structure using an intermediate layer:
public abstract class C : B //abstract intermediate layer
{
// Override-and-seal the base property's getter.
public sealed override int X { get { return this.XGetter; } }
// Define the bridge property for the new class to override.
protected abstract int XGetter { get; }
}
I think that D
is now equivalent to a class inheriting from B
while also being able to override in a setter. Is this correct?
You can always manually disable getter/setter generation for any field by using the special AccessLevel. NONE access level. This lets you override the behaviour of a @Getter , @Setter or @Data annotation on a class.
In C# 8.0 and earlier, the return types of an override method and the overridden base method must be the same. You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method.
That code only requires the setter, not the getter. The interface documents that fact. An interface is just a facility for declaring a group of operations that are "atomically needed" (e.g. if you need to call method A, you'll need to read property B and set property C). So as always, it depends.
What are Getters and Setters? Getters: These are the methods used in Object-Oriented Programming (OOPS) which helps to access the private attributes from a class. Setters: These are the methods used in OOPS feature which helps to set the value to private attributes in a class.
Be careful with your solution as it hides the original intent for A and B. That being said, your solution does work, even when casting to base classes.
Example:
D d = new D();
d.X = 2;
B b = d as B;
Assert.AreEqual(2, b.X);
If the base classes can be modified, I recommend using reflection.
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