Adding a setter to a virtual property in C# - c#

I have a situation like this:
public abstract class BaseClass
{
public abstract string MyProp { get; }
}
Now, for some of the derived classes, the properties value is a synthesized values, so there is no setter:
public class Derived1 : BaseClass
{
public override string MyProp { get { return "no backing store"; } }
}
This works fine. However, some of the derived class required a more traditional backing store. But, no matter how I write it, as on automatic property, or with an explicit backing store, I get an error:
public class Derived2 : BaseClass
{
public override string MyProp { get; private set;}
}
public class Derived3 : BaseClass
{
private string myProp;
public override string MyProp
{
get { return myProp;}
private set { myProp = value;}
}
}
Derived2.MyProp.set': cannot override because 'BaseClass.MyProp' does not have an overridable set accessor
How do I get this to work??

The best thing you can do is implement the property as virtual instead of abstract. Make the get and set blocks for each throw NotSupportedException in the base class and override the behaviour accordingly in derived classes:
public virtual string MyProp {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}

Basically, you cannot. By adding a setter you are changing the definition of the property, so it does not really "override" the base property. It's the same as if you tried to override a method and add another parameter to it - they would be treated as different methods (overloaded). Since properties cannot be overloaded this won't work.
You'll just have to add another method to set the value (perhaps with protected accessibility).

Bradley's suggestion is good, but one thing I've done in cases where only the Setter should be virtual is to do something this this:
public class Root
{
private string _MyProp;
public string MyProp
{
get { return _MyProp;}
set { _MyProp = SetMyProp(value); }
}
protected virtual string SetMyProp(string suggestedValue)
{
return suggestedValue;
}
}
public class Child
: Root
{
protected override string SetMyProp(string suggestedValue)
{
string oReturn = base.SetMyProp(suggestedValue);
// Do some sort of cleanup here?
return oReturn;
}
}
It requires a little extra work up front, but it seems to maintain a higher degree of encapsulation (e.g. you can prevent subclasses from overriding the Getter behavior, and your subclass doesn't have to be aware of the underlying member behind the property).

I would suggest avoiding virtual or abstract properties. Instead, use a non-virtual property which chains to protected virtual or abstract get/set methods. Doing that will allow derived classes to override the methods and also shadow the property with one that has different access modifiers. Since the base property itself will be non-virtual, there will never be any need to override it, so the naming conflict with the new version won't matter.

Related

Unwanted setter of virtual string property, in derived class

Is there a better way of doing the following ...
I have a base class which provides a default implementation of the DisplayName property. Obviously optionally set, not required.
Edit: I can't use an interface instead of this base class, because I have behavior in it, which is trimmed out in this example.
public abstract class BaseObject
{
public virtual string DisplayName { get; protected set; }
public BaseObject(string displayName)
{
if (!string.IsNullOrWhiteSpace(displayName))
{
this.DisplayName = displayName.Trim();
}
}
// There is common behavior, unrelated to DisplayName here ... trimmed out of this sample code.
}
I have a system object class, derived from BaseObject, but providing its own implementation of DisplayName
public class SystemObject : BaseObject
{
public override string DisplayName
{
get
{
return string.Format("TODO: Resources.{0}", this.Id);
}
// EDIT: Turns out I can't even do that, because EF can't materialize the property. So, it needs to be an empty protected setter.
protected set { throw new InvalidOperationException("Do not set this property!"); }
}
public SystemObject() : base(null)
{
}
}
and I have a user-defined object, derived from the same base class:
public class UserObject : BaseObject
{
public UserObject(string displayName) : base(displayName)
{
if (string.IsNullOrWhiteSpace(displayName))
{
throw new ArgumentNullException("displayName");
}
}
public void ChangeDisplayName(string newDisplayName)
{
if (string.IsNullOrWhiteSpace(newDisplayName))
{
throw new ArgumentNullException("newDisplayName");
}
this.DisplayName = newDisplayName.Trim();
}
}
which utilizes the DisplayName from BaseObject to store a user-provided display name.
I can't make the DisplayName in BasObject abstract, because I am doing EF code first.
I am particularly concerned about protected set { throw new InvalidOperationException("Do not set this property!"); }. Any way to avoid this?
Don't use an abstract class at all when you don't actually want to define any behavior. If you just want a way of saying that there are different objects with a DisplayName property getter, then create an interface that defines such a contract that these two classes can implement in their own ways.
I think I see where you are going with this.
Leave the property alone. Just make it a get-only property in the base class, but make the getter call an abstract method:
public string DisplayName { get { return GetDisplayName(); } }
Then declare the method as abstract:
protected abstract string GetDisplayName();
That will force your inheriting classes to provide an implementation of how to return a display name. You can then change your UserObject class to store the name internally during instantiation and return it in the implementation of the method.
You could simply stub it out to do nothing;
public string DisplayName { set {} ...}

How to correctly override and enhance property

Code tells more than words, so look at this:
public abstract class ViewObject: INotifyPropertyChanged {
public virtual string Id {
get {
return this.GetType().Name;
}
}
}
public class Object : ViewObject {
private string id = string.Empty;
public override string Id {
get {
return this.id;
}
set {
this.id = value;
}
}
}
What is the correct way to implement the desired behaviour of a base implementation in the abstract class (yes, it should have a base implementation for this, but not for other things)?
I can only think of using the new keywork instead of override to simply hide the base implementation, but is this right?
you are already using inheritance. Override method is useful when method name and parameter is same.
here you can use method overloading.
for method overload name is same but parameter is different. you can use in inheritance also.
i hope this is useful
If you use the new keyword and someone casts your derived object to the base class, the base implementation will be called and not the derived one. To avoid this, the override is needed.
But that is currently not possible, cause your base class doesn't support a setter. So stick to the override and implement a set method in the base class that simply throws a NotSupportedExecption.
public abstract class ViewObject
{
public virtual string Id
{
get { return this.GetType().Name; }
set { throw new NotSupportedException(); }
}
}
public class Object : ViewObject
{
private string id = string.Empty;
public override string Id
{
get { return this.id; }
set { this.id = value; }
}
}

Correct use of C# 'new' modifier to make protected property public

Let's say I have an abstract base class:
public abstract class BaseClass
{
private MyObject myObject;
protected MyObject PropA
{
get
{
if(myObject == null) this.myObject = new MyObject();
return this.myObject;
}
}
}
...and that in one of my derived classes, I want to make the protected base class property PropA public. Would it be correct to use the new modifier in this context?
public class DerivedClass : BaseClass
{
public new MyObject PropA
{
get
{
return base.PropA;
}
}
}
Would it be correct use of the new modifier in this context?
Technically - yes, there will no errors or warnings.
As for me, using of new keyword itself as a modifier indicates a design drawback.
I'll give one example.
public class MyList<T> : List<T>
{
public int AddCallsCount;
public new void Add(T t)
{
AddCallsCount++;
base.Add(t);
}
}
[TestClass]
public class Test
{
[TestMethod]
public void TestThatsNotGood()
{
List<object> list = new MyList<object>();
list.Add(1);
list.Add(2);
MyList<object> myList = list as MyList<object>;
Assert.AreEqual(0, myList.AddCallsCount);
}
}
It looks like polymorphism works, but actually does not.
UPDATE:
Ok, there is very simplified explanation. I omit explanation of what polymorphism is.
Polymorphims is realized with implementation of abstract\virtual and overriding methods. As soon as neither virtual nor override modifiers are specified MyList<T>.Add is just another 'common' public method. And with MyList<T> inherited List<T>, MyList<T>.Add 'hides' List<T>.Add because name and parameters of both methods are same.
At lower level: as soon as List<T> type definition of method Add isn't marked with virtual keyword, compiler won't search for overriding methods of actual instance type (MyList<T> in this certain case) for variable of given type (List<T> in this certain case).
Definetely it may lead to logic errors and incorrect usage of class API.
Hence, compiler 'thinks' that probably there is a logical mistake or design drawback and warns programmer. The new keyword is just a way to talk to the compiler
yes, I know that it's not good, but I need it because of my bad design
.
The new keyword works and is correct, if you want to add a member in a derived class that has the same name as a member in the base class; however, it seems that this design defies the purpose of abstract classes. Make PropA public and virtual in the base class or public and abstract:
public abstract class BaseClass
{
// Property not implemented here.
public abstract MyObject PropA { get; }
private MyObject _propB;
// Property implemented, but implementation can be overridden in derived class.
public virtual MyObject PropB
{
get { return _propB ?? (_propB = new MyObject()); }
}
public int PropC { get { return 5; } }
}
public class DerivedClass : BaseClass
{
// You must provide an implementation here.
private MyObject _propA;
public override MyObject PropA
{
get { return _propA ?? (_propA = new MyObject()); }
}
// You are free to override this property and to provide an new implementation
// or to do nothing here and to keep the original implementation.
public override MyObject PropB
{
get { return <new implementation...>; }
}
// PropC is inherited as is and is publicly visible through DerivedClass as well.
}
That's correct. Anytime you have a class with a member that has the same name as a member in an inherited class you need to use the new keyword (even if the two properties/methods have different return types).
I would recommend you perhaps
public new string test {
get { return (this as T).test; }
set { (this as T).test = value; }
}
because base give you only parent but if you want to go higher you have to cast.

C# calling parent property while the child property is being called

I wanna see if there is anyway that when the child property method is being called, it will call the parent property as well.
Note that the child is generated by a code generator from edmx. So I can't change anything except adding a partial class for the child class. (It might be too trouble to change the generator.)
The situation I am having :
I have a class "MyClass" that is automatically generated from the database. I can't change anything on it except adding a partial class or change the code generator.
Now, I need to "do something" whenever the property Name is being called. I am thinking if I can put a parent there and make it call the parent to do "something" when the child property is "Name" is being called.
What I want :
public class ClassBase
{
public string Name
{
get
{
CallMethod();
return Name;
}
}
}
public class MyClass : ClassBase
{
public string Name { get; set; }
}
MyClass myClass = new MyClass();
myClass.Name; < -- this will call the parent as well.
Is there anyway to do it?
Thanks in advance
Not really related but since you're not strictly using automatic properties in ClassBase, you should create a private string variable for Name. Something like _name or whatever your internal coding standards dictate.
public class ClassBase
{
private string _name;
public virtual string Name
{
get
{
CallMethod();
return _name;
}
set
{
_name = value;
}
}
}
public class MyClass : ClassBase
{
//Pretty pointless really since you're not doing anything with MyClass.Name.
public new string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
MyClass myClass = new MyClass();
myClass.Name; <-- this will call the parent as well.
Based on "can't change base class" comment there is pretty much nothing you can do to make some code to be executed instead/before/after base class because your property/method will not be called when your new class used as base class (see sample in details part).
Potential solution : if you need to extend specially designed parital class's and it provides extension poinst like CallMethod is marked as partial - it is expected for implemnting portion of the class to implement it :
partial public class ClassBase
{
partial void CallMethod();
public string Name {get {CallMethod(); return "";}}
}
// in generated portion of "ClassBase"
partial public class ClassBase
{
partial void CallMethod() { /* do something here */ }
}
Answer to exact "how to call base class property" is to use base, but hiding property/method this way is confusing (see below):
new public string Name { get { return base.Name;} }
Note that you can't use automatic property in derived class case as you explicitly want some additional code to be executed. If you need set in derived class you need own backing field like:
private string derivedName;
new public string Name {
get { return base.Name + derivedName;}
set { derivedName = value;}
}
Details:
As said in comments hiding base class' properties/methods leads to very confusing behavior. For you case (slightly updated base class with baking field as original sample had infinite recursion):
public class ClassBase
{
private string name;
public string Name
{
get
{
CallMethod();
return name;
}
}
}
You can try to hide Name property in derived class:
public class MyClass : ClassBase
{
// notice "new" to show comiler you know what you doing
// otherwise you'll get warning (but behavior will be the same)
new public string Name { get; set; }
}
The issue with hiding is that base class' method is still easily callable and likely be called by mistake if using derived class as base class:
MyClass myDerved = new MyClass();
ClassBase myDervedAsBase = myDerved;
var name = myDerived.Name; // calls MyClass.Name
var name = myDerivedAsBase.Name; // calls ClassBase.Name
This can be solved by making base class' method/property virtual - but it requires change in base class:
public class ClassBase
{
virtual public string Name { get {... } }
}
public class MyClass : ClassBase
{
override public string Name { get { ... } }
}
If you need to call base class' method/property from derived class usebase.MethodName() like:
override public string Name { get
{
// do some new stuff here
var baseName = base.Name;
// maybe even change result
return baseName;
}
}
If you expect most derived classes to need such behavior it could be better to design base class explicitly to enforce such behavior. For example you can have property to call virtual method before/after computing the value to return like:
public class ClassBase
{
virtual protected string AboutToReturnName(string result)
{
return name;
}
public string Name
{
get
{
var result = "MyName";
return AboutToReturnName(result);
}
}
}
More ideas:
Alternative to virtual is partial methods which works when instead of deriving class is combined from many "partial" parts like ASP.Net pages - see Partial Classes and Methods
If you need notifications around change of property - consider implementing INotifyPropertyChange
if you need to know when properties/method are called in general - consider using interfaces and automatically generate wrapper classes that have pre/post callback. I.e. mocking frameworks (like EasyMoq or RhinoMock) and DI containers (like Unity) provide and use such functionality.
You cannot do it without modifying the code generator. The modification would have to generate a call base.Name.
You can override the property in your subclass with the new operator.
public class MyClass : ClassBase
{
public new string Name { get; set; }
}

C#: Semi-Abstract Automatic Properties?

In a base class, I want to define an abstract get, but at that point, I don't care about the set. How can I define a setter in my child class?
I tried a few things, but I can't get it to work. For example I tried :
public class BaseClass
{
public abstract bool MyBool { get; }
}
public class ChildClass : BaseClass
{
public override bool MyBool { get; protected set;}
}
And :
public class BaseClass
{
public bool MyBool { abstract get; }
}
public class ChildClass : BaseClass
{
public bool MyBool { override get; protected set;}
}
I know I can workaround this by not using automatic properties in the child class and directly setting the underlying field instead of creating a setter, but I'm looking for something better.
Edit: I don't want to add an abstract setter in the BaseClass.
It may make more sense to use an interface rather than a base class. Then you simply have the classes that need to provide that property implement that interface.
For instance, you can create this interface:
public interface IBoolable {
bool MyBool { get; }
}
Then it is still valid to implement the interface like so:
public class BoolableItem : IBoolable {
public bool MyBool { get; protected set; }
}
Done this way, your code can safely assume anything that implements IBoolable has a property called MyBool that is at minimum read-only.
One solution is to make MyProperty not abstract but delegate its implementation to an abstract protected property that children must override:
public abstract class BaseClass
{
public bool MyBool { get { return MyBoolInternal; } }
protected abstract bool MyBoolInternal { get; set; }
}
public class ChildClass : BaseClass
{
protected override bool MyBoolInternal { get; set; }
}
You have to make up your mind what behavior you want: if it is defined as abstract then a deriving class MUST implement it.
So what you should do is this:
public abstract class BaseClass
{
public abstract string MyProperty { get; set; }
}
public class DerivedClass : BaseClass
{
public override string MyProperty
{
get { return "myValue"; }
set { /* do nothing, not applicable for this class */ }
}
}
Don't throw the NotImplementedException - that is not what you want, you simply want the setter to do nothing for some child classes.
To leave it ambiguous whether you want a setter in inherited classes would violate OOP principles--that is, if a class (abstract or not) has a public/protected setter (abstract or not), then all inheriting classes must also; if a class does not, then inheriting classes must not.
Another way to think about this is to consider properties such that read-only or read-write is part of the contract of the class. Since instances of inheriting classes must adhere to an "Is-a relationship" (the LSP), inheriting classes cannot "add a setter" where the main class didn't have one, because the fact that the main class had a property without as setter is part of the main class definition. In effect, since the main class cannot change the property in question via a setter, therefore all inheriting classes MUST guarantee the same behavior.
Consider using a protected backing field; then you can split this property into a read-only property and a separate setter method. Then, the main class can have the property only and the subclass can have a setter method that the main class doesn't know about. However, I'm not sure this would be a good design either.

Categories

Resources