Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override a getter-only property with a setter in C#?

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 overrideing the old one, then we create a bridge method that overrides the old get method with a call to the new one.

Situation

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; } }
}

Problem

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; } }
}

Solution

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?

like image 232
Nat Avatar asked Mar 05 '14 22:03

Nat


People also ask

Can we override setter method?

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.

Can we override a property in C#?

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.

Can we use setter without getter?

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 is property getters and setters?

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.


1 Answers

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.

like image 121
Nathan R Avatar answered Oct 06 '22 01:10

Nathan R