Introduce setter for some - but not all - inherited classes - c#

I am having a hard time implementing a property in C# that only has a getter in the abstract base class, but where I need to introduce a setter in one of the derived classes.
Update: For a shorter explanation of a generalized example of this question, see this question. The selected answer has explained why this is currently impossible to do in C#, however, in my mind no satisfactory solution has yet been provided.
An overview of my class diagram is shown below:
My objective is that the two classes TextElementStatic and TextElementReferenceSource should have a Text property with both getters and setters, while the class TextElementReferenceTarget should have a Text property with only a getter. I'm constantly using ITextElement while referencing all of these objects, and I need to ensure that the ITextElement interface only has a getter. Also, the base class TextElement implements a lot of common code, so all classes need to inherit from that class.
My current code looks like this:
Interface: ITextElement
public interface ITextElement
{
string Text { get; }
}
Interface: ITextElementUpdatable
public interface ITextElementUpdatable : ITextElement
{
new string Text { get; set; }
}
Abstract class: TextElement (This is where my problem is, explained below)
public abstract class TextElement : ITextElement
{
// I want to mark this 'abstract', but that causes my problem
public virtual string Text
{
get
{
// NOTE: This should never be called
Debug.Fail("Called virtual Text getter that should never be called");
return default(string);
}
}
}
Abstract class: TextElementUpdatable
public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable
{
// Should have both a getter and a setter
public new virtual string Text { get; set; }
}
Class: TextElementStatic
public class TextElementStatic : TextElementUpdatable
{
// Should have both a getter and a setter
// No Text property declaration
// Inherits Text property from TextElementUpdatable
}
Class: TextElementReferenceSource
public class TextElementReferenceSource : TextElementUpdatable
{
// Should have both a getter and a setter
public override string Text
{
get { return _internalobject.Text; }
set { _internalobject.Text = value; }
}
}
Class: TextElementReferenceTarget
public class TextElementReferenceTarget : TextElement
{
// Should ONLY have a getter
public override string Text
{
get { return _internalobject.Text; }
}
}
So, my issue is: I really want to declare the Text property in the base class TextElement abstract, because it should always be implemented in the derived classes (both TextElementUpdatable, TextElementReferenceSource and TextElementReferenceTarget implements this property). However, if I try to convert the property to public abstract string Text { get; }, then I receive an error in TextElementUpdatable specifying that
TextElementUpdatable.Text hides the inherited property TextElement.Text
Further, if I change the property in TextElementUpdatable from new to override the error message is replaced by:
Cannot override because TextElement.Text does not have an overridable set accessor
Now, I could go back to TextElement and change the property to public virtual string Text { get; private set; } and call it a day, since that method should never be called anyway (which is basically the solution I have now). However, if I or someone create another derived class later on, I want to force me/them to implement the Text-property, hence I would rather mark it abstract than provide a virtual implementation.
Any suggestions on how I can do this the right way - even if it should involve a lot of refactoring?
I know that I could separate the two objectives her, providing one inherited Text property with only a getter, and then introduce a SetText() method in the ITextElementUpdatable interface. However, I'm wondering whether it is possible to find a good solution with properties only.
Another similar question, but without any answers I've been able to use: C# - What should I do when every inherited class needs getter from base class, but setter only for ONE inherited class

It is really an exciting desing problem, but.. You have to use the new keyword what is not a good practice. Try to avoid them.
Of course, property names can be the same in the interfaces, but if both implemented by a class (and one of the props defined without a setter), we have to implement them explicitelly. We have to accept that these properties "conflict".
You could introduce abstract methods:
public abstract class TextElement : ITextElement
{
public string Text { get { return GetText(); } }
protected abstract string GetText();
}
public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable
{
string ITextElementUpdatable.Text
{
get { return GetText(); }
set { SetText(value); }
}
protected abstract void SetText(string text);
}

It can be a bit confusing that you use the same property in your hierarchy with different meanings. Maybe the implementation of ITextElement.get_Text and ITextElementUpdatable.get_Text will diverge later - the interfaces define two independent behavior, and we do not use basic types all the time, like string.
So my suggestion is that you should have a property in ITextElement for read only purpose, and another property in ITextElementUpdatable with different name. In this manner, your methods can be defined as abstract, of course.

Related

Why not override get-only property with settable property?

Overriding get-only property with settable property is prohibited in C#.
public class Example : IExample //// OR ExampleBase
{
public int Property { get; set; } //// This causes error.
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
I've already checked question 1 and question 2.
I know how to avoid the error, but I don't know why this should be prohibited.
Please let me know why overriding get-only property with settable property is wrong.
TL;DR;
Overriding or implementing get-only property with settable property is prohibited in C#.
Partially correct. It's perfectly valid to implement a get-only property with a settable property - but it's invalid to override a get-only property with a settable property.
The long version:
When I've tried to compile your code, I've got two compilation errors (In VS 2017, if that matters)
Error CS0106 The modifier 'abstract' is not valid for this item
Error CS0106 The modifier 'public' is not valid for this item
When removed the public abstract from the property in the interface, the code compiles just fine (removed the abstract class as it's irrelevant here):
public class Example : IExample
{
public int Property { get; set; }
}
public interface IExample
{
int Property { get; }
}
However, when attempting to use an abstract class and override a get only property with a get/set property, I got this compilation error:
Error CS0546 'Example.Property.set': cannot override because 'ExampleBase.Property' does not have an overridable set accessor
for the following code (removed the interface, same error for a private set):
public class Example : ExampleBase
{
public override int Property { get; set; }
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
This is actually a good way to show the difference between overriding and implementing in c#:
An interface is a contract. It force the implementing types to include it's members as a part of it's public API (explicit implementation aside). So when implementing an interface with a get-only property, you can add a setter to this property, because as long as it has the getter, the contract is still being fulfilled.
However, a base class is not a contract. If forces the inheriting classes to have the exact same member signature, but allows the inheriting class to override virtual members (so the same method or property will be implemented differently in the two classes). In fact, a derived class is a (specific) type of it's base class.
Usually If you want to add a setter to a get-only property in the base class, you will have to shadow it using the keyword new, but this will not help with abstract members - an abstract member must be overriden in the derived class - and since we don't have properties overloads, you will have to add a method to set the value of the get-only property, and implement it explicitly:
public class Example : ExampleBase
{
private int _property;
public override int Property { get { return _property; } }
public void SetProperty(int property)
{
_property = property;
}
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
And for the sake of completeness - here is how you would use the new keyword if the base property was not abstract:
public class Example : ExampleBase
{
public new int Property { get; set; }
}
public class ExampleBase
{
public virtual int Property { get; }
}
The abstract and public modifiers are not available in an interface.
Assuming you meant the following:
public class Example : ExampleBase
{
public override int Property { get; set; } //// This causes error.
//// public int Property { get; private set; } //// This causes error, too.
}
public interface IExample
{
int Property { get; }
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
When you implement an interface (IExample) you can add a setter. When you extend the abstract class (ExampleBase) you have to implement the property the way the abstract base specifies it must be implemented, that is with just a getter.
I can't speak in place of the C# language team but to me I think it comes to consistency and avoiding design mistake.
While the CLR doesn't forbid it - you could think a property as a pair of GetProperty() and SetProperty() methods, for which one could be defined in the base class and the other in a derived class - when bundled into a property you are basically expressing a contract to access a "resource" (usually a field).
So when the base class declares a property to be getter only, you don't expect concrete implementation to expose a setter in the same place. If the concrete class does need to so, then it better conveys its intent by defining a separate method, since it is kind of "breaking" the class contract.
When it comes to interface, on the other hand, the contract is only on a "surface" API: just just say that method or that getter must be implemented. And you could have one interface defining get-only properties and one interface defining set-only properties (why not).

When should I use an abstract property, and when should property be in my abstract class [duplicate]

I'm not really sure what looks better or when do I really use in abstract classes and properties, or when to use non abstract properties. I'll try to make a simple example. Let's say I have this:
abstract class Human
{
public GenderType Gender { get; set; }
public string Name { get; set; }
public Date Born { get; set; }
public bool IsNerd { get; set; }
abstract public void Speak();
abstract public void Sleep();
abstract public void AnoyingPeopleOnStackOverflow();
//... so on
}
class Peter : Human
{
//Peter is special, he got a second name
//But thats all, everything else is the same as like on other humans
public string SecondName { get; set; }
//...override abstract stuff
}
Is this alright? As I understood, I don't have to use an abstract property if I dont want to override it. And in this situation it would be ok, just the methods like Speak, Sleep and so on should be abstract.
Now, if this is ok, when would or should I use an abstract property?
Use an abstract property when you have no default implementation and when derived classes must implement it.
Use a virtual property when you have an implementation in the base class but want to allow overriding.
Use the override keyword to override a member. Mark the member as sealed override if it should not be overridden again.
Don't mark the property as abstract or virtual if you don't want it to be overridden.
Use the new keyword to hide a non-abstract, non-virtual member (this is rarely a good idea).
How to: Define Abstract Properties
I find that abstract properties often occur in a design which implies that they will have type-specific logic and/or side effects. You are basically saying, "here is a data point that all subclasses must have, but I don't know how to implement it". However, properties which contain a large amount of logic and/or cause side effects may not be desirable. This is an important consideration, though there is no fixed right/wrong way to do it.
See:
Should Properties have Side Effects
CA1024: Use properties where appropriate
Personally, I find that I use abstract methods frequently but abstract properties rarely.
I know what I want them to do, I don't care how they do it: Interface.
I know what I want them to do, I don't care how they do some of it, but I've firm ideas on how they'll (or at least most of them) do other bits: Abstract class.
I know what I want them to do, and how most of them will do it: Concrete class with virtual members.
You can have other cases such as e.g. an abstract class with no abstract members (you can't have an instance of one, but what functionality it offers, it offers completely), but they're rarer and normally come about because a particular hierarchy offers itself cleanly and blatantly to a given problem.
(Incidentally, I wouldn't think of a Peter as a type of Human, but of each peter as an instance of human who happens to be called Peter. It's not really fair to pick on example code in this way, but when you're thinking about this sort of issue it's more pertinent than usual).
Abstract members are simply virtual members that you have to override. You use this for something that has to be implemented, but can't be implemented in the base class.
If you want to make a virtual property, and want that it has to be overridden in the class that inherits your class, then you would make it an abstract property.
If you for example have an animal class, its ability to breathe would not be possible to detemine just from the information that it's an animal, but it's something that is pretty crucial:
public abstract class Animal {
public abstract bool CanBreathe { get; }
}
For a fish and a dog the implementation would be different:
public class Dog : Animal {
public override bool CanBreathe { get { return !IsUnderWater; } }
}
public class Fish : Animal {
public override bool CanBreathe { get { return IsUnderWater; } }
}
Use abstract when all sub-classes have to implement the method/property. If there's no need for each and every sub-class to implement it, then don't use it.
As for your example, if SecondName is not required for each person, then there's no need to make an abstract property in the base class. If on the other hand, every person does need a second name, then make it an abstract property.
Example of correct usage of an abstract property:
public class Car
{
public abstract string Manufacturer { get; }
}
public class Odyssey : Car
{
public override string Manufacturer
{
get
{
return "Honda";
}
}
}
public class Camry : Car
{
public override string Manufacturer
{
get
{
return "Toyota";
}
}
}
Making Maker abstract is correct because every car has a manufacturer and needs to be able to tell the user who that maker is.
An abstract property would be used where you want the class to always expose the property, but where you can't pin down the implemetation of that property - leaving it up to/forcing the inheriting class to do so.
There's an example here, where the abstract class is named Shape, and it exposes an abstract Area property. You can't implement the Area property in the base class, as the formula for area will change for each type of shape. All shapes have an area (of some sort), so all shapes should expose the property.
Your implementation itself looks just fine. Was trying to think of a sensible example of an abstract property for a Human, but couldn't think of anything reasonable.

Changing propeprty setter behaviour from a base class

I'm working with Telerik RadScheduleView and have implemented the IAppointment class into a child 'Job' class that I have defined. The 'Start' and 'End' (DateTimes) properties are found in the IAppointment class (of which I inherit). Navigating to the 'Public Virtual' method (in the IAppointment class) shows me a { get; set; } but I can't change it to say, for example, display a MessageBox on setting a new value to Start or End. It says MetaData in the tab, is this just something I am not able to edit? Is there a way I can override this access method somehow??
The name IAppointment would indicate to me that it is not a class you are inheriting, but an interface you're implementing - however, I'm not familiar with Telerik products and their naming conventions might just be weird, so, taking what you say at face value, yes you ought to be able to override a property defined as virtual.
If, for example, we have the following class defined somewhere, but accessible, so that we may inherit, and which exposes a virtual member:
public class A
{
public virtual int J { get; set; }
}
Then we can inherit and override - we may still access the base implementation, but also "inject" our own, if required:
public class B : A
{
public override int J
{
get
{
return base.J;
}
set
{
base.J = value;
}
}
}
But I can't for the life of me imagine why you'd want to show a message box from within the logic of property accessors, and can't stress enough that you shouldn't.
As Mr Disappointment mentioned I'd expect IAppointment to be an interface.
If it is indeed a class you could use the new modifier and do something along the lines of this.
public class Job : IAppointment
{
new public DateTime End
{
get
{
//get the value directly from the base class
return base.End;
}
set
{
//display your messagebox here
//then pass the value to the base class
base.End = value;
}
}
}
you can write a property in your derived class which will eventually get and set the propety of base class no need to override.
First of all, your question is confusing. IAppointment isn't a class, its an interface.
Is this your situation?
There is an interface called IAppointment with 2 properties namely Start and End. ( http://www.telerik.com/help/wpf/t_telerik_windows_controls_scheduleview_iappointment.html )
There is a base implementation named AppointmentBase (or the more derived, Appointment). (http://www.telerik.com/help/wpf/t_telerik_windows_controls_scheduleview_appointmentbase.html)
You are building your own class which is inheriting from the AppointmentBase.
You want the setter of AppointmentBase.End to show a messageBox but you dont know how to add this logic.
In that case i have good news.
AppointmentBase only servers virtual members so you can easily override the Set property
class Job : AppointmentBase
{
public override DateTime End
{
get { return base.End; }
set
{
MessageBox.Show("Unbelievable!");
base.End = value;
}
}
}

How to hide set method of an implemented property from an interface in C#?

Greetings everyone...
If I have the following interface:
interface IMyInterface
{
int property { get; set; }
}
And the following implementation:
class MyClass : IMyInterface
{
// anything
}
How can I hide the set method of property from the instances of MyClass... In other words, I don't want the set method of property to be public, is that possible?
It would be easy to do with abstract class:
abstract class IMyInterface
{
int property { get; protected set; }
}
Then I could only set the property within the class that implements the abstract class above...
Don't have the set in the interface to begin with. You can still implement it as private.
You can't "hide" it, it's part of the contract. If you don't want it to be part of the contract, don't define it.
If you use the following interface the set method will be unavailable when classes are manipulated via the interface:
interface IMyInterface
{
int property { get; }
}
You could then implement the class like this:
class MyClass : IMyInterface
{
int property { get; protected set; }
}
If some implementations will only implement some parts of an interface, it may be a good idea to subdivide the interface into the parts which each implementation will either implement completely or not at all, and then define interfaces which inherit all the common combinations of them. Adapting your example:
interface IMyReadableInterface
{
int property { get; }
}
interface IMyFullInterface : IMyReadableInterface
{
new int property { get; set; }
}
Classes which want to support read-write access should implement IMyFullInterface; those which want to only support read access should only implement IMyReadableInterface. This segregation will not require any extra work for implementations of either interface which are written in C# and implement property implicitly. Code which implements property in VB, or explicitly implements property in C#, will have to define two implementations of property--a read-only one and a read-write one, but such is life. Note that while one could define an IMyWritableInterface which just had a setter, and have IMyFullInterface inherit both IMyReadableInterface and IMyWritableInterface, IMyFullInterface would still have to define a read-write property of its own, and when using explicit implementation one would then have to define three properties (I really don't understand why C# can't use a read-only and write-only property together as thought they were a read-write property, but it can't).
Assuming you need the setter to be part of the interface but for some reason it does not make sense for it to be used on a particular implementer (in this case MyClass) you can always throw an exception in the setter (such as an InvalidOperationException). This will not protect you at compile time, only at run time. It is a bit strange though, as code that operates on the interface has no idea whether calling the setter is allowed.
There are certainly cases where you want the interface to have a set and then hide it in some concrete class.
I believe the code below shows what we want to accomplish. I.e. the implementation hides the setter, but any IMyInterface aware component will have access to it.
public static void Main()
{
var myClass = new MyClass();
myClass.Property = 123; // Error
((IMyInterface)myClass).Property = 123; // OK
}
It's basically the same pattern you often see for IDisposable.Dispose() where you have an Explicit Interface Implementation. Here's an example for completeness.
public interface IMyInterface
{
int Property { get; set; }
}
public class MyClass : IMyInterface, IDisposable
{
public int Property { get; private set; }
int IMyInterface.Property
{
get => Property;
set => Property = value;
}
void IDisposable.Dispose() {}
}
Too much typing :(
C# doesn't help us much here. Ideally, it would be possible to have an explicit interface implementation for the setter:
// In C# 10 maybe we can do this instead:
public class MyFutureClass : IMyInterface
{
public int Property { get; IMyInterface.set; }
}
See C# feature proposal here.
There is no protected or private in interface, everything is public. Either you don't define any set or use it as public.

Accessibility of abstract properties

I have an abstract class with an abstract property that is set to have both Get and Set. I know I'll always want to be able to get this property from derived classes but there are some cases where it doesn't make sense to set this property in certain types of derived classes.
I can't just omit the Set accessor in a derived class (see code example below). I could override the set accessor in a derived classes to do nothing with the values passed by the user. But is there another way that actually make the property in a specific derived class read only? Ultimately I'm displaying these properties in a property grid and I don't want the user to be entering values into a field that is going to do nothing. Maybe I just attribute the property as read only in specific derived classes?
Also I'd really really rather not mess with any of the type descriptor stuff to get properties to display correctly in a property grid, such as overriding ICustomTypeDescriptor.
public abstract class MyClass
{
public abstract string MyProperty
{
get;
set;
}
}
public abstract class MyDerivedClass
{
public override string MyProperty
{
//VS complains that the Set accessor is missing
get;
}
}
You should not do this. What you are saying by defining your getter and setter in the abstract class is "you must implement this if you want to inherit from me." Then you are asking, "how can I made a derived class ignore this rule."
The answer is that if you have a situation that every derived class needs a getter, put that in the abstract class and let the derived class decide if they will implement a setter or not by leaving it out of the abstract class.
Or alternatively, you can create two more classes that derive from the initial abstract class, one that implement the setter and one that does not and then have your derived class generalize the one of those that makes sense, but that is overkill I think.
look like you searching for
[ReadOnly(true)] attribute
this will show to property grid your property, as readonly.
but in your class you can use it as usual property (with read and write possibilities)
You should use abstract not override:
public abstract class MyClass
{
public abstract string MyProperty
{
get;
set;
}
}
public abstract class MyDerivedClass
{
public abstract string MyProperty
{
get;
}
}
but like #JP wrote, you shouldn't do this.

Categories