Changing propeprty setter behaviour from a base class - c#

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

Related

Manage derived classes via a base class when using GetComponent in Unity?

Whenever I try to set up an inheritance hierarchy, I find myself trapped in this scenario over and over.
In the current form, I have a base class that represent all UI elements in my game. I called this class, UI_Toggleable. This class has an enum property that each derived class can set. Here is brief look as to how the code looks like:
public class UI_Toggleable
{
// The Menu Type enum that all derived classes must define.
protected UIMenus menuType;
// Gives any child of this class a toggle function
// to enable/disable UI when needed.
public void ToggleUI()
{
// Toggle Code
}
// Public property Getter - Read Only Access.
// Only derived classes can define the value of the menu type.
public virtual UIMenus MenuType
{
get { return menuType; }
}
}
Now, say a class called InventoryUI derives from Toggleable, we have the following.
public class InventoryUI : UI_Toggleable
{
private void Awake()
{
_instance = this;
menuType = UIMenus.Inventory;
}
public override UIMenus MenuType
{
get { return menuType; }
}
}
Now, if I try to implement a manager for these objects, I will want to get the menu type of each derived class. However, I do not want to ASSUME the type of the UI_Toggleable class. Instead, what I am trying to do is to get any of the derived classes as a UI_Toggleable, and then proceed to call the MenuType method to get its type regardless.
UI_Toggleable toggleable = GetComponent<UI_Toggleable>();
toggleable.MenuType;
The problem with the above is, it would return me the MenuType of the base class instead of the derived class I retrieved as a base class. And that is somewhat expected, but I want to get the MenuType of the derived class WITHOUT doing the following:
if(GetComponent<UI_Toggleable>() is InventoryUI )
InventoryUI toggleable = GetComponent< InventoryUI >();
toggleable.MenuType;
The above works, but it defeats the purpose of me setting up a base class that shares similar properties with children. Doing all these casts and checks just makes the code appear difficult to read and decouple.
Other things I tried include the following:
Create an interface IMenuType that defines a function GetMenuType. Each derived class implements the method, and in my manager, I would do the check if(toggleable is IMenuType). And if true, then attempt to call ((IMenuType)toggleable).GetMenuType.
Let the MenuType property getter be an abstract function that each derived class must implement. But similar to the above cases, I still have to make cast checks before attempting to call the method.
Although not my priority, the MenuType method was not meant to be virtual.
You are not setting menuType of the base class correctly. Rather than setting it in the Awake method of derived classes, set it in the constructor, like this:
public class UI_Toggleable {
public UIMenus MenuType {get;}
// Subclasses must pass the correct menuType here
protected UI_Toggleable(UIMenus menuType) {
MenuType = menuType;
}
}
public class InventoryUI : UI_Toggleable {
// Pass the proper menu type for storing inside the base class
public InventoryUI() : base(UIMenus.Inventory) {
}
}
Note how MenuType is now a read-only property of the base class, rather than a virtual property with overriding.
I cannot really use the constructor. Is it acceptable if I set it in the Awake method instead?
It appears from your code sample that Awake is not being called in time for the base class to supply the correct value. In this case you go with an abstract getter-only property, like this:
public class UI_Toggleable {
public abstract UIMenus MenuType {get;}
}
public class InventoryUI : UI_Toggleable {
public override UIMenus MenuType {
get => UIMenus.Inventory
}
}
Note: Legacy syntax for get => UIMenus.Inventory is get { return UIMenus.Inventory; }

How to fix inherited member hiding warning when dealing with virtual properties

I have the following base class:
public class OAuthRefreshToken {
//Other properties..
public int UserId { get; set; }
public virtual OAuthUser User { get; set; }
}
And this derived class:
public abstract class OAuthRefreshToken<U> : OAuthRefreshToken
where U : OAuthUser {
public virtual U User { get; set; }
}
What I want is to override the User property from the OAuthRefreshToken base class with the one in my derived class.
I thought of adding the override keyword:
public override virtual U User { get; set; }
But this throws a compilation error as it is not allowed.
If I leave the code like that (without override) a warning appears saying I'm hiding inherited member (which I intend to do).
It tells me to use override if hiding is intended...
And then we are on a nice loop where the warning tells you do something and the compiler tells you not to do it.
Of course, I'll listen to the compiler, but how can I fix the warning? I don't like building my project and have a nice bunch of warnings appear.
Thank you for your time.
You can't change the type of the property when overriding it. If you want to change the type, you need to hide the method instead of overriding it. If you want to override it instead of hiding it, you'll need to maintain the same type that the base class uses.
The warning should tell you what you can do - something like this (emphasis mine):
'OAuthRefreshToken.User' hides inherited member 'OAuthRefreshToken.User'.
To make the current member override that implementation, add the override keyword.
Otherwise add the new keyword.
However, presumably you want the two properties to do be about the same value - so you need to also override the property from the base class.
Now, there's a problem because you can't have two properties with the same name but different types declared in the same type... so I'd suggest using a different name for the new property - at which point you don't need to declare it with new because it doesn't hide anything.
public abstract class OAuthRefreshToken<U> : OAuthRefreshToken where U : OAuthUser
{
public override OAuthUser User
{
get { return TypedUser; }
set { TypedUser = (U) value; }
}
public virtual U TypedUser { get; set; }
}
I suspect there may be alternatives where you go back to hiding the property if you introduce an intermediate class, but that's almost certainly going to be even uglier.

Introduce setter for some - but not all - inherited classes

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.

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.

Why is it impossible to override a getter-only property and add a setter? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Why is the following C# code not allowed:
public abstract class BaseClass
{
public abstract int Bar { get;}
}
public class ConcreteClass : BaseClass
{
public override int Bar
{
get { return 0; }
set {}
}
}
CS0546 'ConcreteClass.Bar.set': cannot override because 'BaseClass.Bar' does not have an overridable set accessor
I think the main reason is simply that the syntax is too explicit for this to work any other way. This code:
public override int MyProperty { get { ... } set { ... } }
is quite explicit that both the get and the set are overrides. There is no set in the base class, so the compiler complains. Just like you can't override a method that's not defined in the base class, you can't override a setter either.
You might say that the compiler should guess your intention and only apply the override to the method that can be overridden (i.e. the getter in this case), but this goes against one of the C# design principles - that the compiler must not guess your intentions, because it may guess wrong without you knowing.
I think the following syntax might do nicely, but as Eric Lippert keeps saying, implementing even a minor feature like this is still a major amount of effort...
public int MyProperty
{
override get { ... } // not valid C#
set { ... }
}
or, for autoimplemented properties,
public int MyProperty { override get; set; } // not valid C#
It's possible.
tl;dr– You can override a get-only method with a setter if you want. It's basically just:
Create a new property that has both a get and a set using the same name.
override the prior get to alias the new get.
This enables us to override properties with get/set even if they lacked a setter in their base definition.
Situation: Pre-existing get-only property.
You have some class structure that you can't modify. Maybe it's just one class, or it's a pre-existing inheritance tree. Whatever the case, you want to add a set method to a property, but can't.
public abstract class A // Pre-existing class; can't modify
{
public abstract int X { get; } // You want a setter, but can't add it.
}
public class B : A // Pre-existing class; can't modify
{
public override int X { get { return 0; } }
}
Problem: Can't override the get-only with get/set.
You want to override with a get/set property, but it won't compile.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Solution: Use an abstract intermediate layer.
While you can't directly override with a get/set property, you can:
Create a new get/set property with the same name.
override the old get method with an accessor to the new get method to ensure consistency.
So, first you write the abstract intermediate layer:
public abstract class C : B
{
// Seal off the old getter. From now on, its only job
// is to alias the new getter in the base classes.
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
Then, you write the class that wouldn't compile earlier. It'll compile this time because you're not actually override'ing the get-only property; instead, you're replacing it using the new keyword.
public class D : C
{
private int _x;
public new virtual int X
{
get { return this._x; }
set { this._x = value; }
}
// Ensure base classes (A,B,C) use the new get method.
protected sealed override int XGetter { get { return this.X; } }
}
Result: Everything works!
var d = new D();
var a = d as A;
var b = d as B;
var c = d as C;
Print(a.X); // Prints "0", the default value of an int.
Print(b.X); // Prints "0", the default value of an int.
Print(c.X); // Prints "0", the default value of an int.
Print(d.X); // Prints "0", the default value of an int.
// a.X = 7; // Won't compile: A.X doesn't have a setter.
// b.X = 7; // Won't compile: B.X doesn't have a setter.
// c.X = 7; // Won't compile: C.X doesn't have a setter.
d.X = 7; // Compiles, because D.X does have a setter.
Print(a.X); // Prints "7", because 7 was set through D.X.
Print(b.X); // Prints "7", because 7 was set through D.X.
Print(c.X); // Prints "7", because 7 was set through D.X.
Print(d.X); // Prints "7", because 7 was set through D.X.
Discussion.
This method allows you to add set methods to get-only properties. You can also use it to do stuff like:
Change any property into a get-only, set-only, or get-and-set property, regardless of what it was in a base class.
Change the return type of a method in derived classes.
The main drawbacks are that there's more coding to do and an extra abstract class in the inheritance tree. This can be a bit annoying with constructors that take parameters because those have to be copy/pasted in the intermediate layer.
Bonus: You can change the property's return-type.
As a bonus, you can also change the return type if you want.
If the base definition was get-only, then you can use a more-derived return type.
If the base definition was set-only, then you can use a less-derived return type.
If the base definition was already get/set, then:
you can use a more-derived return type if you make it set-only;
you can use a less-derived return type if you make it get-only.
In all cases, you can keep the same return type if you want.
I stumbled across the very same problem today and I think I have a very valid reason for wanting this.
First I'd like to argue that having a get-only property doesn't necessarily translate into read-only. I interpret it as "From this interface/abstract class you can get this value", that doesn't mean that some implementation of that interface/abstract class won't need the user/program to set this value explicitly. Abstract classes serve the purpose of implementing part of the needed functionality. I see absolutely no reason why an inherited class couldn't add a setter without violating any contracts.
The following is a simplified example of what I needed today. I ended up having to add a setter in my interface just to get around this. The reason for adding the setter and not adding, say, a SetProp method is that one particular implementation of the interface used DataContract/DataMember for serialization of Prop, which would have been made needlessly complicated if I had to add another property just for the purpose of serialization.
interface ITest
{
// Other stuff
string Prop { get; }
}
// Implements other stuff
abstract class ATest : ITest
{
abstract public string Prop { get; }
}
// This implementation of ITest needs the user to set the value of Prop
class BTest : ATest
{
string foo = "BTest";
public override string Prop
{
get { return foo; }
set { foo = value; } // Not allowed. 'BTest.Prop.set': cannot override because 'ATest.Prop' does not have an overridable set accessor
}
}
// This implementation of ITest generates the value for Prop itself
class CTest : ATest
{
string foo = "CTest";
public override string Prop
{
get { return foo; }
// set; // Not needed
}
}
I know this is just a "my 2 cents" post, but I feel with the original poster and trying to rationalize that this is a good thing seems odd to me, especially considering that the same limitations doesn't apply when inheriting directly from an interface.
Also the mention about using new instead of override does not apply here, it simply doesn't work and even if it did it wouldn't give you the result wanted, namely a virtual getter as described by the interface.
I agree that not being able to override a getter in a derived type is an anti-pattern. Read-Only specifies lack of implementation, not a contract of a pure functional (implied by the top vote answer).
I suspect Microsoft had this limitation either because the same misconception was promoted, or perhaps because of simplifying grammar; though, now that scope can be applied to get or set individually, perhaps we can hope override can be too.
The misconception indicated by the top vote answer, that a read-only property should somehow be more "pure" than a read/write property is ridiculous. Simply look at many common read only properties in the framework; the value is not a constant / purely functional; for example, DateTime.Now is read-only, but anything but a pure functional value. An attempt to 'cache' a value of a read only property assuming it will return the same value next time is risky.
In any case, I've used one of the following strategies to overcome this limitation; both are less than perfect, but will allow you to limp beyond this language deficiency:
class BaseType
{
public virtual T LastRequest { get {...} }
}
class DerivedTypeStrategy1
{
/// get or set the value returned by the LastRequest property.
public bool T LastRequestValue { get; set; }
public override T LastRequest { get { return LastRequestValue; } }
}
class DerivedTypeStrategy2
{
/// set the value returned by the LastRequest property.
public bool SetLastRequest( T value ) { this._x = value; }
public override T LastRequest { get { return _x; } }
private bool _x;
}
You could perhaps go around the problem by creating a new property:
public new int Bar
{
get { return 0; }
set {}
}
int IBase.Bar {
get { return Bar; }
}
I can understand all your points, but effectively, C# 3.0's automatic properties get useless in that case.
You can't do anything like that:
public class ConcreteClass : BaseClass
{
public override int Bar
{
get;
private set;
}
}
IMO, C# should not restrict such scenarios. It's the responsibility of the developer to use it accordingly.
The problem is that for whatever reason Microsoft decided that there should be three distinct types of properties: read-only, write-only, and read-write, only one of which may exist with a given signature in a given context; properties may only be overridden by identically-declared properties. To do what you want it would be necessary to create two properties with the same name and signature--one of which was read-only, and one of which was read-write.
Personally, I wish that the whole concept of "properties" could be abolished, except that property-ish syntax could be used as syntactic sugar to call "get" and "set" methods. This would not only facilitate the 'add set' option, but would also allow for 'get' to return a different type from 'set'. While such an ability wouldn't be used terribly often, it could sometimes be useful to have a 'get' method return a wrapper object while the 'set' could accept either a wrapper or actual data.
Here is a work-around in order to achieve this using Reflection:
var UpdatedGiftItem = // object value to update;
foreach (var proInfo in UpdatedGiftItem.GetType().GetProperties())
{
var updatedValue = proInfo.GetValue(UpdatedGiftItem, null);
var targetpropInfo = this.GiftItem.GetType().GetProperty(proInfo.Name);
targetpropInfo.SetValue(this.GiftItem, updatedValue,null);
}
This way we can set object value on a property that is readonly. Might not work in all the scenarios though!
You should alter your question title to either detail that your question is solely in regards to overriding an abstract property, or that your question is in regards to generally overriding a class's get-only property.
If the former (overriding an abstract property)
That code is useless. A base class alone shouldn't tell you that you're forced to override a Get-Only property (Perhaps an Interface). A base class provides common functionality which may require specific input from an implementing class. Therefore, the common functionality may make calls to abstract properties or methods. In the given case, the common functionality methods should be asking for you to override an abstract method such as:
public int GetBar(){}
But if you have no control over that, and the functionality of the base class reads from its own public property (weird), then just do this:
public abstract class BaseClass
{
public abstract int Bar { get; }
}
public class ConcreteClass : BaseClass
{
private int _bar;
public override int Bar
{
get { return _bar; }
}
public void SetBar(int value)
{
_bar = value;
}
}
I want to point out the (weird) comment: I would say a best-practice is for a class to not use its own public properties, but to use its private/protected fields when they exist. So this is a better pattern:
public abstract class BaseClass {
protected int _bar;
public int Bar { get { return _bar; } }
protected void DoBaseStuff()
{
SetBar();
//Do something with _bar;
}
protected abstract void SetBar();
}
public class ConcreteClass : BaseClass {
protected override void SetBar() { _bar = 5; }
}
If the latter (overriding a class's get-only property)
Every non-abstract property has a setter. Otherwise it's useless and you shouldn't care to use it. Microsoft doesn't have to allow you to do what you want. Reason being: the setter exists in some form or another, and you can accomplish what you want Veerryy easily.
The base class, or any class where you can read a property with {get;}, has SOME sort of exposed setter for that property. The metadata will look like this:
public abstract class BaseClass
{
public int Bar { get; }
}
But the implementation will have two ends of the spectrum of complexity:
Least Complex:
public abstract class BaseClass
{
private int _bar;
public int Bar {
get{
return _bar;
}}
public void SetBar(int value) { _bar = value; }
}
Most Complex:
public abstract class BaseClass
{
private int _foo;
private int _baz;
private int _wtf;
private int _kthx;
private int _lawl;
public int Bar
{
get { return _foo * _baz + _kthx; }
}
public bool TryDoSomethingBaz(MyEnum whatever, int input)
{
switch (whatever)
{
case MyEnum.lol:
_baz = _lawl + input;
return true;
case MyEnum.wtf:
_baz = _wtf * input;
break;
}
return false;
}
public void TryBlowThingsUp(DateTime when)
{
//Some Crazy Madeup Code
_kthx = DaysSinceEaster(when);
}
public int DaysSinceEaster(DateTime when)
{
return 2; //<-- calculations
}
}
public enum MyEnum
{
lol,
wtf,
}
My point being, either way, you have the setter exposed. In your case, you may want to override int Bar because you don't want the base class to handle it, don't have access to review how it's handling it, or were tasked to hax some code real quick'n'dirty against your will.
In both Latter and Former (Conclusion)
Long-Story Short: It isn't necessary for Microsoft to change anything. You can choose how your implementing class is set up and, sans the constructor, use all or none of the base class.
Solution for only a small subset of use cases, but nevertheless: in C# 6.0 "readonly" setter is automatically added for overridden getter-only properties.
public abstract class BaseClass
{
public abstract int Bar { get; }
}
public class ConcreteClass : BaseClass
{
public override int Bar { get; }
public ConcreteClass(int bar)
{
Bar = bar;
}
}
This is not impossible. You simply have to use the "new" keyword in your property. For example,
namespace {
public class Base {
private int _baseProperty = 0;
public virtual int BaseProperty {
get {
return _baseProperty;
}
}
}
public class Test : Base {
private int _testBaseProperty = 5;
public new int BaseProperty {
get {
return _testBaseProperty;
}
set {
_testBaseProperty = value;
}
}
}
}
It appears as if this approach satisfies both sides of this discussion. Using "new" breaks the contract between the base class implementation and the subclass implementation. This is necessary when a Class can have multiple contracts (either via interface or base class).
Hope this helps
Because that would break the concept of encapsulation and implementation hiding. Consider the case when you create a class, ship it, and then the consumer of your class makes himself able to set a property for which you originally provide a getter only. It would effectively disrupt any invariants of your class which you can depend on in your implementation.
Because a class that has a read-only property (no setter) probably has a good reason for it. There might not be any underlying datastore, for example. Allowing you to create a setter breaks the contract set forth by the class. It's just bad OOP.
A read-only property in the base class indicates that this property represents a value that can always be determined from within the class (for example an enum value matching the (db-)context of an object). So the responsibillity of determining the value stays within the class.
Adding a setter would cause an awkward issue here:
A validation error should occur if you set the value to anything else than the single possible value it already has.
Rules often have exceptions, though. It is very well possible that for example in one derived class the context narrows the possible enum values down to 3 out of 10, yet the user of this object still needs to decide which one is correct. The derived class needs to delegate the responsibillity of determining the value to the user of this object.
Important to realize is that the user of this object should be well aware of this exception and assume the responsibillity to set the correct value.
My solution in these kind of situations would be to leave the property read-only and add a new read-write property to the derived class to support the exception.
The override of the original property will simply return the value of the new property.
The new property can have a proper name indicating the context of this exception properly.
This also supports the valid remark: "make it as hard as possible for misunderstandings to crop up" by Gishu.
Because at the IL level, a read/write property translates into two (getter and setter) methods.
When overriding, you have to keep supporting the underlying interface. If you could add a setter, you would effectively be adding a new method, which would remain invisible to the outside world, as far as your classes' interface was concerned.
True, adding a new method would not be breaking compatibility per se, but since it would remain hidden, decision to disallow this makes perfect sense.
Because the writer of Baseclass has explicitly declared that Bar has to be a read-only property. It doesn't make sense for derivations to break this contract and make it read-write.
I'm with Microsoft on this one.
Let's say I'm a new programmer who has been told to code against the Baseclass derivation. i write something that assumes that Bar cannot be written to (since the Baseclass explicitly states that it is a get only property).
Now with your derivation, my code may break. e.g.
public class BarProvider
{ BaseClass _source;
Bar _currentBar;
public void setSource(BaseClass b)
{
_source = b;
_currentBar = b.Bar;
}
public Bar getBar()
{ return _currentBar; }
}
Since Bar cannot be set as per the BaseClass interface, BarProvider assumes that caching is a safe thing to do - Since Bar cannot be modified. But if set was possible in a derivation, this class could be serving stale values if someone modified the _source object's Bar property externally. The point being 'Be Open, avoid doing sneaky things and surprising people'
Update: Ilya Ryzhenkov asks 'Why don't interfaces play by the same rules then?'
Hmm.. this gets muddier as I think about it.
An interface is a contract that says 'expect an implementation to have a read property named Bar.' Personally I'm much less likely to make that assumption of read-only if I saw an Interface. When i see a get-only property on an interface, I read it as 'Any implementation would expose this attribute Bar'... on a base-class it clicks as 'Bar is a read-only property'. Of course technically you're not breaking the contract.. you're doing more. So you're right in a sense.. I'd close by saying 'make it as hard as possible for misunderstandings to crop up'.

Categories