greenoldman
greenoldman

Reputation: 21062

How to make partial virtual property?

Design -- in a perfect world

I have one abstract base class A with property Value, and two derived classes W and R. It is always possible to read the Value (and the method is always the same -- reading stored value), so I would put getter directly to A.

However writing to Value is not always possible, and thus there are W and R. W provides also a setter, while R does not -- it just relies on features that come from A.

The problem is, no matter what I tried, I cannot make such design come to life in C#. I cannot override Value property in W because there is no setter in base class (and there is not, because adding a setter to base class means it would "leak" to R as well).

Reality -- the ugly workaround (dont't read)

I added a setter in A which throws an exception. In W I override setter while in R I do nothing.

This is ugly, because of the design, because setter in R is public and because now such code compiles:

R reader;
reader.Value = 5;

The question

So how to make a property with only getter in base class, and add a setter in derived class?

The story

Because there is always at least one curious soul, I explain -- those classes are data holders/managers. The R class is dynamic data "holder" -- it computes value using given formula (similar to Lazy Eval class). Most of of stuff is common among W and R -- filtering values, sending notifications, and so on. The only difference is in R you cannot set the value directly, because the formula in one-way (similar to WPF converter with only one method defined, Convert).

Solution

Thank to Marc I solved this issue, here is the code:

  abstract class A {
      public int Value { get { return ... } }
  }

  class R : A { }

  class W : A {
      new public int Value {
          get { return base.Value; }
          set { .... }
      }
  }

The difference to Marc version is lack of setter in base class (it was the whole point of the question), the difference to my workaround is shadowing the property, not overriding it. Small, but crucial piece.

Thank you Marc for enlightenment :-).

Upvotes: 6

Views: 1103

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062770

abstract class A {
    public int Value {get; protected set;}
}
class R : A { }
class W : A {
    new public int Value {
        get { return base.Value; }
        set { base.Value = value; }
    }
}

Upvotes: 7

Related Questions