shadowed field does not get set in base class constructor - c#

Why is it that when I set a shadowed field (declared using new keyword) in a base class constructor, the field that was shadowed gets set but not the field that is shadowing?
I thought that this.GetType() referred to the outermost class all the way down into base class calls including the constructor. I also thought that shadowing made the shadowed field not accessible.
In my quick watch I can see two fields, the shadowed one that got set and the shadowing one (of the subclass) that is still not initialized.
I fixed it by explicitly setting the shadowing field in the subclass constructor after it calls the base class constructor, but I'd still like to know why it acts this way. .Net Fiddle
using System;
public class Program
{
public static void Main()
{
SubClass subClass = new SubClass(2);
Console.WriteLine(subClass.MyField);
}
}
public class BaseClass
{
public BaseClass(int value)
{
MyField = value; // This doesn't point to SubClass.MyField
}
public int MyField;
}
public class SubClass : BaseClass
{
public SubClass(int value):base(value)
{
}
public new int MyField = 4;
}
Update
After reviewing the answers, I see I didn't ask what I wanted to know in the most direct way. Sorry for any inconvenience. Here's what I really want to know:
I do understand shadowing. I don't agree with it. I don't think it should be allowed for fields (as long as overridable fields were made a language feature). I don't see the point in shadowing fields and having the shadowed field hanging around. I do however see the point in overridable fields and I don't understand why that language feature doesn't exist when it exists for properties and methods. So, why have shadowing on fields? Why is there not overriding on fields?

We have
I also thought that shadowing made the shadowed field not accessible.
Followed by
I do understand shadowing.
I'm not entirely sure that you do. You've already expressed one false belief about shadowing; how do we know there aren't more?
I don't agree with it.
Your opinion is noted. I note that you are not required to use the feature if you don't like it.
I don't think it should be allowed for fields (as long as overridable fields were made a language feature).
Noted.
I do however see the point in overridable fields and I don't understand why that language feature doesn't exist when it exists for properties and methods.
Fields should be private implementation details of classes. If they are, then there is no accessible name to shadow or override, so the problem is moot. A feature that we would want no one to use is a bad feature.
So, why have shadowing on fields?
Suppose there is a protected field in a derived class. Now consider the brittle base class problem. Work through a number of such scenarios; you're critiquing a language design choice, so think like the language designers think. What do you conclude from your investigation into typical brittle base class scenarios?
Why is there not overriding on fields?
Because (1) we have no mechanism for overriding fields; methods have vtables but there is no vtable mechanism for fields. And (2) fields should be private implementation details of classes, and therefore there is never a need to override them. If you want to override a field, make a property that wraps it and override that. The code change is tiny to go from a field to a virtual property.
Fields should be in the mechanism domain of the class; properties are in the business domain. Specialization of behaviour belongs in the business domain.

public class BaseClass
{
public BaseClass(int value)
{
MyField = value; // This doesn't point to SubClass.MyField
}
public int MyField;
}
The base class doesn't know about its derived types. MyField = value does exactly what it says it's doing: it assigns MyField with value.
public class SubClass : BaseClass
{
public SubClass(int value):base(value)
{
}
public new int MyField = 4;
}
Are you expecting the value 4 to propagate to the base type? Your question is quite hard to answer, because it's not exactly clear what your definition of "intuitive" and expectations are.... and your example code is very poor OOP design.
There aren't lots of valid reasons to ever expose a public field, base class or not.
Let me rephrase your example:
public abstract class BaseClass
{
protected BaseClass(int value)
{
_value = value;
}
private int _value;
public virtual int Value { get { return _value; } set { _value = value; } }
}
public class SubClass : BaseClass
{
public SubClass(int value) : base(value)
{
}
public new int Value { get; set; } // hides base class member
}
Now. SubClass.Value is its own thing - if you want to access the value that was passed down the constructor, you need to do so via the base class.
The base class member doesn't "cease to exist", it's only hidden, or shadowed, by a new member in a derived type, that just so happens to have the same identifier:
var foo = new SubClass(42);
Console.WriteLine(foo.Value);
Console.WriteLine(((BaseClass)foo).Value);
Console.ReadKey();
This code outputs 0, then 42 - because when foo.Value gets accessed the SubClass says "hey base class, let me handle this - I have my own definition of Value, and this call mine to pick up." ...and returns 0 because, well, it's never actually assigned; the 42 is only visible via the base class.
That is what member shadowing does.
And it works the same even without the new keyword - the new keyword merely suppresses a compiler warning that says "you're hiding a base class member here, are you really totally completely sure you intend to be doing this?" - because in a normal world, that typically isn't what you would want to be doing.
Now, notice I made the Value property virtual. What happens if you override it instead?
public class SubClass : BaseClass
{
public SubClass(int value)
: base(value)
{
}
public override int Value { get; set; }
}
The little console program above (a few snippets up) will now output 0 and 0 - because the subclass' Value overrides the base class member, effectively telling C# to resolve member calls to the derived type. So to output the 42 you're passing in, because you're overriding the member, you become responsible for how it works - the _value private field in the base class still says 42, but the Value property being overridden, the field is left unused.
So you assign it in your derived type's constructor (here sealing the class to avoid a virtual member call in the constructor):
public sealed class SubClass : BaseClass
{
public SubClass(int value)
: base(0)
{
Value = value;
}
public override int Value { get; set; }
}
So, here the derived type is passing 0 to the base class, and overriding the member. What does the little snippet output for 42 now?
static void Main(string[] args)
{
var foo = new SubClass(42);
Console.WriteLine(foo.Value);
Console.WriteLine(((BaseClass)foo).Value);
Console.ReadKey();
}
it will output 42 for both the derived and the downcasted calls, because the type cast is now redundant, since the virtual member is overridden.

Not sure why you want to do this, but here is how :
public class BaseClass
{
public BaseClass(int value)
{
SetValue(x => x.MyField, value);
}
public int MyField;
public void SetValue<TField>(Expression<Func<BaseClass, TField>> memberSelector, TField value)
{
var expression = memberSelector.Body as MemberExpression;
if (expression == null)
throw new MemberAccessException();
this.GetType().GetField(expression.Member.Name)
.SetValue(this, value);
}
}

Keep in mind that shadowing a field just makes a new field, it is in no way related to the field in the base class (except by virtue of the fact that you've given it the same name).
Simply put, you haven't written any code that sets the field in SubClass, you've only written code that sets the field in BaseClass:
public class BaseClass
{
public BaseClass(int value)
{
MyField = value; // This doesn't point to SubClass.MyField
}
public int MyField;
}
MyField here can only ever refer to the MyField in BaseClass. It can't possibly know that you're going to create a subclass later and put a field in it with the same name. And even if you do that, all you've done is create a different field with the same name, so why would setting BaseClass.MyField also set the mostly unrelated SubClass.MyField?

Related

Visibility of properties in derived classes (C#)

I have been making some hamfisted attempts to apply correct OOP principles to my project. I have an abstract class called DocumentSection, and several classes deriving from it (DocumentSectionView, DocumentSectionText, etc). Similarly I have an abstract class (DocAction) with several classes deriving from it (DocumentActionReplaceByTag, DocumentSectionAppend, etc). Each DocumentSection has a DocumentAction within it.
My understanding of all this inheritance business is that by specifying a 'DocumentAction', this would allow any of those derived classes to be put in its place, and that any properties/methods from the base class would be available, as well as any specified in the concrete class I instantiate. So in the below example, I expected to be able to see the PerformAction method (leaving the virtual/override keywords out of the mix for now). And it is available.
However, because I went v.DocAction = new DocumentActionReplaceByTag();, I would also have expected my ReplaceActionFindText property to be visible.
Obviously I've got it wrong somewhere - any comments appreciated.
class Program
{
static void Main(string[] args)
{
DocumentSectionView v = new DocumentSectionView();
v.DocAction = new DocumentActionReplaceByTag();
// would like to go:
//v.DocAction.ReplaceActionFindText...
Console.ReadLine();
}
}
public abstract class DocumentSection
{
public abstract string GetContent();
public DocumentAction DocAction { get; set; }
}
public class DocumentSectionView : DocumentSection
{
public string ViewPath { get; set; }
public dynamic ViewModel { get; set; }
public override string GetContent()
{
return "test";
}
}
public abstract class DocumentAction
{
void PerformAction(StringBuilder sb, string content);
}
public class DocumentActionReplaceByTag : DocumentAction
{
public string ReplaceActionFindText { get; set; }
public void PerformAction(StringBuilder sb, string content)
{
sb.Replace(ReplaceActionFindText, content);
}
}
EDIT:
I've marked an answer as correct, but thought I'd add the fruits of my further thought on this matter for those coming across this later:
a) As pointed out, my intentions were broadly right but my method wrong. Setting the 'Action's property from the Main method was not correct. In all cases, a a DocumentActionReplaceByTag requires the FindText so I placed it in the constructor:
public DocumentActionReplaceByTag(string replaceActionFindText)
{
this.ReplaceActionFindText = replaceActionFindText;
}
From then on, a constructor with 0 arguments will rightly fail, and prevent a case where the action is executed but no findtext is specified.
b) Polymorphism works fine now, because my extra property findtext has been populated, and running PerformAction will run correctly regardless of the action type.
Because you are assigning your derived class to a property with the type of the base class only the methods and properties of the base class will be available. And this makes sense since you could have assigned any instance of a class that derives from the base class - so any derived methods cannot be used in this context.
This is one of the OOP principles - your derived class instances may be used as an instance of a base class (but not the other way round)
Edit:
To elaborate on the solution proposed by #sll to cast to a particular derived class type: Don't do it! It is a workaround but not in the interest of the overall design.
If you have to cast to a derived type then you are violating the Liskov substitution principle meaning that any derived type should be usable in place of the base type - that's clearly not the case if you need a specific cast.
Rethink your design - do you really need a property with the base class type and if so are the methods currently only in one particular derived type better off being in the base type as well?
The v reference type is of the DocumentSectionView which is not aware of methods of the DocumentActionReplaceByTag class even underlying instance is of DocumentActionReplaceByTag as you've assigned it. You need to cast it to be able accesing derived class members:
((DocumentActionReplaceByTag)v.DocAction).ReplaceActionFindText
Also in some cases this is pretty fine when underlying instance could not be casted so some part of code should be skipped, then you can use exception-safe way of casting using as operator:
var typedAction = v.DocAction as DocumentActionReplaceByTag;
if (typedAction != null)
{
// accessing the typedAction.ReplaceActionFindText property
}
My suggestions are only to help you understand C# side of question, regarding overall design and approach please see BrokenGlass's answer.
No, in your example, since DocAction is only a DocumentAction, you will only be able to see the properties of a DocumentAction, no matter which derived type of DocumentAction is used.

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 force overriding a method in a descendant, without having an abstract base class?

Question Heading seems to be little confusing, But I will Try to clear my question here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public abstract class Employee
{
private string name;
private int empid;
BenefitPackage _BenefitPackage = new BenefitPackage();
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public int EmpId
{
get { return this.empid; }
set
{
if (value == 1)
return;
this.empid = value; }
}
public Employee(string Name, int EmpId)
{
this.Name = Name;
this.EmpId = EmpId;
}
public Employee()
{ }
public abstract void GiveBonus();
}
public class Manager : Employee
{
private int noofstockoptions;
public override void GiveBonus()
{
Console.WriteLine("Manger GiveBonus Override");
}
public int NoOfStockOptions
{
get { return this.noofstockoptions; }
set { this.noofstockoptions = value; }
}
public Manager(string Name,int EmpId, int NoOfStockOptions):base(Name,EmpId)
{
this.NoOfStockOptions=NoOfStockOptions;
}
}
public class SalesPerson:Employee
{
private int noofsales;
public int NoOfSales
{
get { return this.noofsales; }
set { this.noofsales = value; }
}
public SalesPerson(string Name, int EmpId, int NoOfSales):base(Name,EmpId)
{
this.NoOfSales = NoOfSales;
}
public override void GiveBonus()
{
Console.WriteLine("Hi from salesperson");
}
}
public sealed class PTSalesPerson : SalesPerson
{
private int noofhrworked;
public int NoOfHrWorked
{
get { return this.noofhrworked; }
set { this.noofhrworked = value; }
}
public PTSalesPerson(string Name, int EmpId, int NoOfSales,int NoOfHrWorked):base(Name,EmpId,NoOfSales)
{
this.NoOfHrWorked = NoOfHrWorked;
}
//public new void GiveBonus()
//{
// Console.WriteLine("hi from ptsalesperson");
//}
}
class BenefitPackage
{
public int Bonus;
public int GiveBonus()
{
int i = 200;
return i;
}
private class innerPublic
{
public int innerBonus;
}
}
class MainClass
{
public static void Main()
{
Manager _Manager=new Manager("Vaibhav",1,50);
PTSalesPerson _PTSalesPerson = new PTSalesPerson("Shantanu", 1, 4, 6);
_Manager.GiveBonus();
Employee _emp;
//_emp = new Employee("new emp",4);
//_emp.GiveBonus();
_PTSalesPerson.GiveBonus();
((SalesPerson)_PTSalesPerson).GiveBonus();
Console.ReadLine();
}
}
}
Please do not try to understand the whole code. I am summarising it.
Employee is a Abstract class, which have an abstract method GiveBonus
SalesPerson is a deriving from Employee. SalesPerson has to give definition to abstract Method GiveBonus.(SalesPerson can not be Abstract)
PTSalesPerson is deriving from SalesPerson.
Now my question is, How can I force PTSalesPerson to have its own implementation of GiveBonus.
I think you're thinking about this the wrong way. The language designers did not say to themselves "what we really need is a way to mark a method as must be overridden, let's invent this thing called abstract". They said "A virtual method lets us represent the idea that every derived type of this base type should be able to do this method. But what if there is no sensible code that can possibly go in the base class version of the method? I know, let's invent this thing called an abstract method for that circumstance."
That's the problem that abstract methods were intended to solve: you have a method common to all derived classes but no sensible base class implementation, NOT "I need a way to force my derived types to provide an implementation". That derived types are forced to provide an implementation is a consequence of the solution, but not the problem intended to be solved in the first place.
The C# language does not have a mechanism for the problem "I must force my subtype to provide their own implementation of this method" because that's not a problem that the language designers, to my knowledge, ever considered would be a problem for the majority of our customers.
So my question to you is: why do you want to do this? Surely it is up to the developer of the derived class to determine whether or not the base class implementation is correct for the derived class or not. That's not up to you. And even if you did have some way to do that, what would stop the developer from simply saying
override void M() { base.M(); }
?
Can you explain what purpose you have for attempting to force this work upon the developers of your derived classes? Perhaps there is a better way to achieve what you want.
But more generally: I am not sure that your hierarchy is sensibly designed in the first place. When I see a method GiveBonus on an Employee, I assume that this means that "an employee can give a bonus", not "an employee can receive a bonus". Surely a manager gives a bonus and an employee receives a bonus. I think you might be making the employee hierarchy do too much.
You can not, unless you make SalesPerson abstract or change the hierarchy.
How about:
Employee*
^
|
SalesPersonBase* (have all the code except GiveBonus)
^ ^
| |
SalesPerson PTSalesPerson
Both Employee and SalesPersonBase are now marked as abstract.
However, if you require a PTSalesPerson to not only inherit behavior, but also inherit the is-a relationship (a PTSalesPerson is also a SalesPerson), then you have no way of forcing this.
Note, the above text is only valid if you only consider compile-time checks. In other words, if you want the compiler to complain if you haven't added an override to the PTSalesPerson class, you cannot do that, unless you do what I outlined above.
However, there's nothing stopping you from using reflection to examine the methods at runtime, and throw an exception if the method in PTSalesPerson is not explicitly overridden there, however I would consider that a hack.
This is a very old thread but the answer given on this question can be usefull.
You can force a derived class to have its own implementation of a virtual method/property.
public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}
public abstract class E : D
{
public abstract override void DoWork(int i);
}
public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}
If a virtual method is declared abstract, it is still virtual to any
class inheriting from the abstract class. A class inheriting an
abstract method cannot access the original implementation of the
method—in the previous example, DoWork on class F cannot call DoWork
on class D. In this way, an abstract class can force derived classes
to provide new method implementations for virtual methods.
Declare the class Employee as abstract, the class SalesPerson as concrete (non-abstract), and provide an implementation of GiveBonus() that throws a runtime exception with a message like "Must be implemented by subclasses" for any types or cases which the provided code is not supposed to cover. It's an old Smalltalk practice. I have used it in Java code.
if (GetType() != typeof(SalesPerson))
{
throw new NotImplementedException("Please override in subclasses");
}
// ...proceed with giving SalesPerson a bonus
Use dependency injection. Create a BonusCalculator class:
public abstract class BonusCalculator
{
public abstract decimal CalculateBonus(Employee e)
}
In your base class:
private BonusCalculator Calculator { get; set; }
public void GiveBonus()
{
Bonus = Calculator.CalculateBonus(this)
}
In your implementation's constructor:
public SomeKindOfEmployee()
{
Calculator = new SomeKindOfEmployeeBonusCalculator();
}
Someone implementing a Person subclass now has to explicitly provide it with an instance of a BonusCalculator (or get a NullReferenceException in the GiveBonus method).
As an added, er, bonus, this approach allows different subclasses of Person to share a bonus-calculation method if that's appropriate.
Edit
Of course, if PTSalesPerson derives from SalesPerson and its constructor calls the base constructor, this won't work either.
A WA may be using an "Interface" so you define one like IBonusGiver { void GiveBonus(); }
An then, instead of the abstract method and the overrides, you implement in all your classes this new interface. e.g. PTSalesPerson : SalesPerson, IBonusGiver forcing a new implementation in each class.
You can't using the setup you described. PTSalesPerson will already have an implementation of GiveBonus because it inherits from SalesPerson.
I feel like this indicates that your implementation really has two parts: a partial implementation that goes in the base class, and a missing completion to that implementation that you want in the sub class. Ex:
public abstract class Base
{
public virtual void PartialImplementation()
{
// partial implementation
}
}
public sealed class Sub : Base
{
public override void PartialImplementation()
{
base.PartialImplementation();
// rest of implementation
}
}
You want to force the override, since the initial implementation is incomplete. What you can do is split your implementation into two parts: the implemented partial part, and the awaiting-implementation missing part. Ex:
public abstract class Base
{
public void PartialImplementation()
{
// partial implementation
RestOfImplementation();
}
// protected, since it probably wouldn't make sense to call by itself
protected abstract void RestOfImplementation();
}
public sealed class Sub : Base
{
protected override void RestOfImplementation()
{
// rest of implementation
}
}
If you aren't going to create a SalesPerson instance directly, then the simplest thing to do would be to make SalesPerson abstract and that would force any child classes to implement it instead (or be abstract themselves).
If there is some logic in that method common to all SalesPeople, then you could implement GiveBonus on SalesPerson as a template method. Which calls some abstract method required in any subclasses:
Which ever way you decide, the only way to force an implementation in a child class is to make the base class abstract.
The only way i can see of making this work, if you can not make SalesPerson Abstract, is this:
1) in SalesPerson.GiveBonus(...) use reflection to determine if 'this' is a SalesPerson, or a derived class
a) if not a derived class, do current code in SalesPerson.GiveBonus
b) otherwise call GiveBonusDerived. (declare this as virtual, and make the implmentation in SalesPerson throw an exception.)
The draw backs here are, Reflection is slow. No compile time error if GiveBonusDerived isn't declared, etc.
You could always make SalesPerson's implementation throw a NotImplementedException. :V But contractually, no, you can't do that.
This is pretty old, but we have a somewhat similar situation. The base class loads a configuration file and sets up base class defaults. However, the configuration file could also contain default values for inherited classes.
This is how we got the combined functionality.
Base class methods
private void processConfigurationFile()
{
// Load and process the configuration file
// which happens to be an xml file.
var xmlDoc = new XmlDocument();
xmlDoc.Load(configurationPath);
// This method is abstract which will force
// the inherited class to override it.
processConfigurationFile(xmlDoc);
}
protected abstract void processConfigurationFile(XmlDocument document);
Okay, I know this post is old, however, I have recently needed to look this answer up, so for anyone else looking for this: (I am using VS 2012 .net 4.5, so not sure about older versions)
I created an abstract class, and used override on both child classes:
public abstract class Person
{
public string Name { get; protected set; }
public abstract void GiveName(string inName);
}
public class Employee : Person
{
public override void GiveName(string inName)
{
Name = inName;
}
}
public class SalesPerson:Employee
{
public override void GiveName(string inName)
{
Name = "Sales: "+inName;
}
}
Testing:
SalesPerson x = new SalesPerson();
x.GiveName("Mark"); //Name="Sales: Mark"
Employee e = x;
e.GiveName("Mark"); //Name="Sales: Mark"
Employee m = new Employee();
m.GiveName("Mark"); //Name="Mark"
I very much hope my answer will help some people confused by this issue.
Bear with me, but I'll try to re-summarise what is being asked, just to ensure that I am answering the right question. Then I'll give the answer!
I think the essence of the question is: How do I declare a method in an abstract class so that is has an implementation but still requires a derived class to override the method?
C# doesn't appear to support this. If you declare the method 'abstract', it is not permitted to have an implementation (body). But if you declare it 'virtual', a derived class is not forced to override it. C# deosn't allow a method to be marked as both abstract and virtual.
I believe there are many situations where you wish to do this (what is being asked).
The way to solve this riddle is as follows: Declare two methods! One of them is marked 'abstract'; the other is marked 'virtual' and calls the first one somewhere in its body.
This way, the derived class is forced to override the abstract method, but the (partial) implementation in the virtual method can be safely inherited.
So, for example, the Employee method GiveBonus might be declared thus:
public abstract decimal ComputeBonus();
public virtual void GiveBonus() {
decimal amount = ComputeBonus();
if (amount > 0.0) PostBonus(amount);
}
I'll leave the details of PostBonus to the imagination, but the beauty of this approach is that derived classes are forced to override ComputeBonus, yet GiveBonus benefits from the partial implementation provided in the base class. HTH

C#, implement 'static abstract' like methods

I recently ran into a problem where it seems I need a 'static abstract' method. I know why it is impossible, but how can I work around this limitation?
For example I have an abstract class which has a description string. Since this string is common for all instances, it is marked as static, but I want to require that all classes derived from this class provide their own Description property so I marked it as abstract:
abstract class AbstractBase
{
...
public static abstract string Description{get;}
...
}
It won't compile of course. I thought of using interfaces but interfaces may not contain static method signatures.
Should I make it simply non-static, and always get an instance to get that class specific information?
Any ideas?
You can't.
The place to do this is with Attributes.
Eg
[Name("FooClass")]
class Foo
{
}
If you don't mind deferring to implementations to sensibly implement the Description property, you can simply do
public abstract string ClassDescription {get; }
// ClassDescription is more intention-revealing than Description
And implementing classes would do something like this:
static string classDescription="My Description for this class";
override string ClassDescription { get { return classDescription; } }
Then, your classes are required to follow the contract of having a description, but you leave it to them to do it sensibly. There's no way of specifying an implementation in an object-oriented fashion (except through cruel, fragile hacks).
However, in my mind this Description is class metadata, so I would prefer to use the attribute mechanism as others have described. If you are particularly worried about multiple uses of reflection, create an object which reflects over the attribute that you're concerned with, and store a dictionary between the Type and the Description. That will minimize the reflection (other than run time type inspection, which isn't all that bad). The dictionary can be stored as a member of whatever class that typically needs this information, or, if clients across the domain require it, via a singleton or context object.
If it is static, there is only one instance of the variable, I don't see how inheritance would make sense if we could do what you want to accomplish with static vars in derived classes. Personally I think you are going to far to try to avoid a instance var.
Why not just the classic way?
abstract class AbstractBase
{
protected string _Description = "I am boring abstract default value";
}
class Foo : AbstractBase {
public Foo() {
_Description = "I am foo!";
}
}
Combining static and abstract is somewhat meaningless, yes. The idea behind static is one need not present an instance of the class in order to use the member in question; however with abstract, one expects an instance to be of a derived class that provides a concrete implementation.
I can see why you'd want this sort of combination, but the fact is the only effect would be to deny the implementation use of 'this' or any non-static members. That is, the parent class would dictate a restriction in the implementation of the derived class, even though there's no underlying difference between calling an abstract or 'static abstract' member (as both would need a concrete instance to figure out what implementation to use)
A possible workaround is to define a Singleton of your derived class in your base class with the help of Generics.
import System;
public abstract class AbstractBase<T>
where T : AbstractBase<T>, new()
{
private static T _instance = new T();
public abstract string Description { get; }
public static string GetDescription()
{
return _instance.Description;
}
}
public class DerivedClass : AbstractBase<DerivedClass>
{
public override string Description => "This is the derived Class";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(DerivedClass.GetDescription());
Console.ReadKey();
}
}
The trick is to tell your AbstractBase<T> some details about how DerivedClass is implemented:
It is newable with where T: new() so it can create a Singleton instance
It derives from itself with where T : AbstractBase<T> so it knows that there will be a implementation of Description
This way _instance contains the Description field which can be called in the static Method GetDescription().
This forces you to overwrite Descriptionin your DerivedClass and allows you to call its value with DerivedClass.GetDescription()
It's not static if it has to be called on an instance.
If you're not calling it on an instance, then there's no polymorphism at play (i.e. ChildA.Description is completely unrelated to ChildB.Description as far as the language is concerned).
You can...
In the abstract class...
protected abstract InWindow WindowInstance { get; set; }
In the derived class...
private static InWindow _instance;
protected override InWindow WindowInstance
{
get => _instance;
set => _instance = value;
}
You could make the "abstract" base method throw an Exception, so then a developer is "warned" if he tries to invoke this method on a child class without overriding.
The downside is that one might extend the class and not use this method. Then refer to other answers provided.

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