carlito_brigante wrote:
So to be fully sure my thinking is really correct please tell yes or not to my two statements: First case: I don't know since beginning whether derived classes inheriting from abstract base class would need to control values or not so I would implement like below then if some derived class don't want to control value then don't need to override this but just use Id directly from abstract base class and that's it but if some derived class would like to control Id then need to override Id for it own and create private field _id as well…
Wrong.
Let's see why would you need a property (not field) at all. You need it only because of its setter, or getter, or both, to provide some side effect on reading or writing the property value. Why having auto-implemented properties (with just
{ get; set; }
instead of "real" getter and setter? Just because you want to preserve such possibility in future.
Your first flaw in your consideration is: "I don't know since beginning whether derived classes inheriting from abstract base class would need to control values or not, so…". If you don't know that, it means that you should assume that the derived class will have to control it. Isn't it obvious?
The second big flaw is that you think that explicit backing fields can add anything at all. In fact, auto-implemented backing
is strictly equivalent to similar explicit backing (not counting the subtle but practically non-considerable problem of the name of that backing field). Having auto-implemented backing does not limit the ability to add those side effects in any way.
Your code in the comment I referenced won't even compile and does not makes sense, so I'll write proper illustrative example:
abstract class MyAbstractClass {
protected virtual string Id { get; set; }
}
class MyDerivedClassWhichDoesNothingUseful : MyAbstractClass {
protected string _id;
protected override string Id { get { return _id; } set { _id = value; } }
}
class MyDerivedClassWhichCanMakeSomeSense : MyAbstractClass {
protected string id;
protected override string Id {
get {
DoSomethingOnRead(id);
return id;
}
set {
if (id == value) return;
DoSomethingOnWrite(id, value);
id = value;
}
}
void DoSomethingOnRead(string value) { }
void DoSomethingOnWrite(string oldValue, string newValue) { }
}
Is it clear now?
Let me tell you again: your original code is questionable is some other ways: the role of the interface (which is only needed when you use late binding, polymorphic methods receiving parameters of some interface
compile-time, mixing interfaces with virtual method/property mechanisms (nothing wrong about it, but everything should have its purpose), and so on. I only caught what seemed obvious from the first glance.
—SA