How to override a getter-only property with a setter in C#? - c#

Update: This question has been revised to make it clearer. The answers below seem to reflect that this method works well. Hopefully this question can help people who need to add a get or set to an existing property.
Ran into a problem today where I needed to override a base class's get-only property with both a get and set. Current consensus seems to be that this is impossible, but I think that I found a method.
The general idea is to make a new property instead of directly overrideing the old one, then we create a bridge method that overrides the old get method with a call to the new one.
Situation
Here's some code for an arbitrary pre-existing type structure that can't be modified.
public abstract class A
{
public abstract int X { get; }
}
public class B : A
{
public override int X { get { return 0; } }
}
Problem
We'd like to write this code, but it won't compile.
public class C : B // won't compile: X can't have a 'set' method
{
private int _x;
public override int X { get { return _x; } set { _x = value; } }
}
Solution
We write the code we want anyway, but we declare the property to be new instead of override, allowing us to declare a set method.
public class D : C // Same thing, but will compile because X is 'new'
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } } // also 'virtual', unless we want to 'sealed' it.
// Bridge method provides the override functionality:
protected sealed override int XGetter { get { return this.X; } } // 'sealed' because this bridge should always refer to the new 'get' method
}
The extra bridge method, XGetter, provides the override. This is glued to the base class structure using an intermediate layer:
public abstract class C : B //abstract intermediate layer
{
// Override-and-seal the base property's getter.
public sealed override int X { get { return this.XGetter; } }
// Define the bridge property for the new class to override.
protected abstract int XGetter { get; }
}
I think that D is now equivalent to a class inheriting from B while also being able to override in a setter. Is this correct?

Be careful with your solution as it hides the original intent for A and B. That being said, your solution does work, even when casting to base classes.
Example:
D d = new D();
d.X = 2;
B b = d as B;
Assert.AreEqual(2, b.X);
If the base classes can be modified, I recommend using reflection.

UPDATE:
The following is INCORRECT.
No.
public abstract class A
{
public abstract int X { get; }
public int GetXPlusOne()
{
return X + 1;
}
}
You won't change the value of A.X.
var d = new D();
d.X = 10;
d.GetXPlusOne() == 1

By introducing the new property XGetter in your example, you've made the solution more complex than it needs to be. You can introduce the same property and just reverse which property gets the getter and setter.
public abstract class A
{
public abstract int X { get; }
}
public class D : A
{
private int _x;
public sealed override int X { get { return XGetterSetter; } }
public virtual int XGetterSetter { get { return this._x; } set { this._x = value; } }
}
There's just as much code in class D in the above example as there is in your original example. This just eliminates the need for class B and class C from your example.
Semantically, this solution may not be the same. You'd have to set the XGetterSetter property as opposed to the X property. Derived classes of D would also have to override XGetterSetter as opposed to X.

Related

C#: Trying to invoke a method in a class

I am programming a game. Each level has a class (level1, level2, etc) that tells the game which objects to set up plus other stuff. Each level shares an interface iLevel.
All objects in the scene have access to anything in iLevel, but sometimes I want to call a method that only exists in the specific level class.
For example:
public class Level1, iLevel {
public int GetANumber() {
return 5;
}
}
The calling class needs to do this:
public class SomeObject {
iLevel myLevel = new iLevel();
int x = ... // now I need to call GetANumber() without knowing that object is Level1, Level2, etc.
}
I believe I need to use invoke somehow, but I wasn't able to get it to work. I read the documentation on msdn but I still wasn't able to get it to work.
Thank you so much for help!
Here either u can use if condition with is and as operators or make iLevel an abstract class with GetNumber returning negative values by default.
public class SomeObject {
iLevel myLevel = new iLevel();
int x = -1;
if(myLevel is Level1) {
x = (myLevel is Level1).GetANumber();
}
}
Or
public abstract class iLevel {
public virtual int GetANumber() {
return -1;
}
}
public class Level1 : iLevel {
public override int GetANumber() {
return 5;
}
}

abstract class constructor inheritence with inner classes objects

Let s say I got an abstract class A. There I got some inner classes like here:
public abstract class A
{
public InnerOne x;
public InnerTwo y;
public A(){
this.x = new InnerOne();
this.y = new InnerTwo();
}
public class InnerOne
{
public virtual double value(){
return 0;
}
}
public class InnerTwo
{
public virtual double value(){
return 0;
}
}
}
Then I got it's childrens like this one:
public class B: A
{
public B():base(){
}
public class InnerOne: A.InnerOne
{
public override virtual double value(){
return 100;
}
}
public class InnerTwo: A.InnerTwo
{
public override virtual double value(){
return 100;
}
}
}
So I was think that when I call B constructor like that I will initialize x and y by creating it's inner classes instances. But actually it not works like that. When I call vaule functions like here it returns zeros.
A newobject = new B();
var bv1 = B.x.value();
var bv2 = B.y.value();
Is there way to force B class to initialize it's x and y fields by it's inner class objects (not with objects from parent abstract class) without re-writing it's constructor?
Even though you have defined the classes inside A or B, they are still public and they are accessible outside A or B. Its no different from a class definied outside A or B.
Imagine the same code with the InnerOne and InnerTwo defined outside the class A and B. It will have the same above behavior. Your root of confusion is misunderstanding inner class usage.
Inorder to get 100, inside B you need to explicitly replace the instance of X and Y variables with an instance that overrides those values. Unless you do them you will not get 100.
public class B: A
{
public B():base(){
X = new OverridenInnerOne();
Y = new OverridenInnerTwo();
}
public class OverridenInnerOne: A.InnerOne
{
public override virtual double value(){
return 100;
}
}
public class OverridenInnerTwo: A.InnerTwo
{
public override virtual double value(){
return 100;
}
}
}
You can do it, but you must change the definition for class A - and it gets super hairy.
Here's A:
public abstract class A<I1, I2>
where I1 : A<I1, I2>.InnerOne, new()
where I2 : A<I1, I2>.InnerTwo, new()
{
public InnerOne x;
public InnerTwo y;
public A()
{
this.x = new I1();
this.y = new I2();
}
public class InnerOne
{
public virtual double value()
{
return 0;
}
}
public class InnerTwo
{
public virtual double value()
{
return 0;
}
}
}
And here's B:
public class B: A<B.InnerOne, B.InnerTwo>
{
public B():base(){ }
public class InnerOne: A<InnerOne, InnerTwo>.InnerOne
{
public override double value()
{
return 100;
}
}
public class InnerTwo: A<InnerOne, InnerTwo>.InnerTwo
{
public override double value()
{
return 100;
}
}
}
B.x and B.y are instances of A.InnerOne and A.InnerTwo, so you're seeing the value returned as 0 as these have nothing to do with B.InnerOne or B.InnerTwo.
The following B constructor would assign x and y to instances of B.InnerOne and B.InnerTwo which would return 100.
public B(){
this.x = new InnerOne();
this.y = new InnerTwo();
}
If you wanted A to work in the way you expect, you'd need to pass the inner types you wanted through from the B constructor and create instances of them in the A constructor, something like:
public B():base(typeof(InnerOne),typeof(InnerTwo)) { ... }
Using Activator.CreateInstance will let you create these types within A's constructor.
Enigmativity's generic solution is better if you always want A used this way, alternatively this way allows you to have multiple constructors for A so you could optionally pass in different types.
The 'inner class' aspect (embedded class definition) only distracts here, it plays no role.
And to answer the question: No, you cannot have 'virtual constructors' that work this way.
There are of course plenty of ways to get 100 instead of 0 as returnvalue but the question is too artificial to suggest one.

Inheritance misunderstanding in C#

I am trying to understand the way inheritance works in C#. Basically, I have a base class Base that has a simple function sayIt. The function makes use of a property "i" that is redefined in subclasses. Here, it is redefined as 1 from 0. When I run this program, I get "0" as output rather than "1" which is what I expected (because in python I would get 1). Can anyone explain why, and more importantly, whether this is a pattern that is supported in C#?
class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
Console.WriteLine(d.sayIt());
Console.ReadLine();
}
}
class Base
{
int _i = 0;
public int i
{
get { return _i; }
}
public String sayIt()
{
return Convert.ToString(this.i);
}
}
class Derived : Base
{
int _i = 1;
public new int i
{
get { return _i; }
}
}
Mark the property as virtual within Base class
Replace new with override next to the property within Derived class.
1. Is necessary because members are non-virtual in c# by default. and 2. is necessary, because using new would break the virtual resolving pass, what is not what your want.
There is nice article about new and override on MSDN: Knowing When to Use Override and New Keywords (C# Programming Guide).
The override modifier extends the base class method, and the new modifier hides it.
In order to have a function that can be overriden by a derived type you need to make it virtual
public virtual int i
{
get { return _i; }
}
Then in the derived type you can override the behavior with the override keyword
public override int i
{
get { return _i; }
}
In C# you have the option to NOT allow full polymorphic/inheritance behavior in your classes.
In order to get your expected output your code should look like this: (didn't test)
class Base
{
int _i = 0;
public virtual int i
{
get { return _i; }
}
public String sayIt()
{
return Convert.ToString(this.i);
}
}
class Derived : Base
{
int _i = 1;
public override int i
{
get { return _i; }
}
}
Now you are telling the C# interpreter that i is "virtual" or the underlying representation can be overridden by child classes.
In your old code, you are calling sayIt() which is in Base(). Since i is NOT virtual, it does not look for a child porperty that has been overridden.
Basically in C#, in order to have proper inheritance and polymorphism your code needs explicit declaration in syntax by the use of "virtual" then "override".
As others have mentioned change the property i to virtual in the Base and use override in the property in the Derived class. See below example for the output for each case to understand it better. You can see that you get different output for Option 2.
class Base
{
int _i = 0;
public virtual int i
{
get { return _i; }
}
public String sayIt()
{
return Convert.ToString(this.i);
}
}
class Derived : Base
{
int _i = 1;
public override int i
{
get { return _i; }
}
}
You can instantiate the code in 3 different ways:
// Option 1
Base a = new Base();
Console.WriteLine(a.i);
// Output using virtual/override --> 0
// Output using new --> 0
// Option 2
Base b = new Derived();
Console.WriteLine(b.i);
// Output using virtual/override --> 1
// Output using new --> 0
// Option 3
Derived c = new Derived();
Console.WriteLine(c.i);
// Output using virtual/override --> 1
// Output using new --> 1
// Option 2
// Derived d = new Base();
// Console.WriteLine(d.i);
// This won't obviously compile
The confusion is because you are technically using name hiding in the derived class instead of overriding the base class' behavior. When using member hiding, the type you have the reference to dictates which method actually runs as both exist. New allows you to indicate you intended to "hide" the base implementation for those specifically calling your method on the designated type. To illustrate:
class Program
{
static void Main(string[] args)
{
//both 'i' properties exist
Derived d = new Derived();
Console.WriteLine(d.i); // uses the 'i' for this type
Console.WriteLine(((Base)d).i); // uses the 'i' for this type
Console.ReadLine();
}
}
class Base
{
int _i = 0;
public int i
{
get { return _i; }
}
public String sayIt()
{
//this class and this method doesn't realize the derived class has hid this.i
return Convert.ToString(this.i);
}
}
class Derived : Base
{
int _i = 1;
public new int i
{
get { return _i; }
}
}
This is what you want I believe to achieve the pattern.
class Base
{
int _i = 0;
public virtual int i
{
get { return _i; }
}
public String sayIt()
{
return Convert.ToString(this.i);
}
}
class Derived : Base
{
int _i = 1;
public override int i
{
get { return _i; }
}
}
Hope that helps.
-dw

C# splitting property get and set between classes. Why doesn't it work?

I'm trying to provide two classes to my users - one that is read-only and one that is writable. The r/o will only have getters, while the writable will inherit from it and add the setters.
I was under the impression that C# should be able to handle it, but the compiler disagreed.
Why doesn't this work? Any workarounds?
class A
{
protected int m_val;
public int Val
{
get { return m_val; }
}
}
class B : A
{
public int Val
{
set { m_val = value; }
}
}
class Test
{
static void Main(string[] args)
{
B b = new B();
b.Val++; // <-- WHY DOESN'T THIS WORK?!
}
}
P.S. the protected variable in the example above is artificial. My class actually wraps some native resources and the getting/setting happens on either const or mutable native pointer.
partial applies to a single type - not 2 types (A and B). You would need something more like below, ideally keeping the field private:
class A
{
private int m_val;
public int Val
{
get { return m_val; }
protected set { m_val = value; }
}
}
class B : A
{
public new int Val
{
get { return base.Val;}
set { base.Val = value; }
}
}
I'm not sure about why you need this, but a possibly better design would be to have two interfaces rather than two classes, and a single class that implements both. Then you could hand your client code whichever interface you'd like them to use, with the added bonus of being able to use the values set on a writable interface and hand it over to someone else as a read-only interface.
Mark the setters as protected in the parent, and expose public setters in the child.

Overriding fields or properties in subclasses

I have an abstract base class and I want to declare a field or a property that will have a different value in each class that inherits from this parent class.
I want to define it in the baseclass so I can reference it in a base class method - for example overriding ToString to say "This object is of type property/field".
I have got three ways that I can see of doing this, but I was wondering - what is the best or accepted way of doing this? Newbie question, sorry.
Option 1:
Use an abstract Property and override it on the inherited classes. This benefits from being enforced (you have to override it) and it is clean. But, it feels slightly wrong to return a hard-code value rather than encapsulate a field and it is a few lines of code instead of just. I also have to declare a body for "set" but that is less important (and there is probably a way to avoid that which I am not aware of).
abstract class Father
{
abstract public int MyInt { get; set;}
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
set { }
}
}
Option 2
I can declare a public field (or a protected field) and explicitly override it in the inherited class. The example below will give me a warning to use "new" and I can probably do that, but it feels wrong and it breaks the polymorphism, which was the whole point. Doesn't seem like a good idea...
abstract class Mother
{
public int MyInt = 0;
}
class Daughter : Mother
{
public int MyInt = 1;
}
Option 3
I can use a protected field and set the value in the constructor. This seems pretty tidy but relies on me ensuring the constructor always sets this and with multiple overloaded constructors there is always a chance some code path won't set the value.
abstract class Aunt
{
protected int MyInt;
}
class Niece : Aunt
{
public Niece()
{
MyInt = 1;
}
}
It's a bit of a theoretical question and I guess the answer has to be option 1 as it is the only safe option but I am just getting to grips with C# and wanted to ask this of people with more experience.
Of the three solutions only Option 1 is polymorphic.
Fields by themselves cannot be overridden. Which is exactly why Option 2 returns the new keyword warning.
The solution to the warning is not to append the “new” keyword, but to implement Option 1.
If you need your field to be polymorphic you need to wrap it in a Property.
Option 3 is OK if you don’t need polymorphic behavior. You should remember though, that when at runtime the property MyInt is accessed, the derived class has no control on the value returned. The base class by itself is capable of returning this value.
This is how a truly polymorphic implementation of your property might look, allowing the derived classes to be in control.
abstract class Parent
{
abstract public int MyInt { get; }
}
class Father : Parent
{
public override int MyInt
{
get { /* Apply formula "X" and return a value */ }
}
}
class Mother : Parent
{
public override int MyInt
{
get { /* Apply formula "Y" and return a value */ }
}
}
Option 2 is a non-starter - you can't override fields, you can only hide them.
Personally, I'd go for option 1 every time. I try to keep fields private at all times. That's if you really need to be able to override the property at all, of course. Another option is to have a read-only property in the base class which is set from a constructor parameter:
abstract class Mother
{
private readonly int myInt;
public int MyInt { get { return myInt; } }
protected Mother(int myInt)
{
this.myInt = myInt;
}
}
class Daughter : Mother
{
public Daughter() : base(1)
{
}
}
That's probably the most appropriate approach if the value doesn't change over the lifetime of the instance.
You could do this
class x
{
private int _myInt;
public virtual int myInt { get { return _myInt; } set { _myInt = value; } }
}
class y : x
{
private int _myYInt;
public override int myInt { get { return _myYInt; } set { _myYInt = value; } }
}
virtual lets you get a property a body that does something and still lets sub-classes override it.
option 2 is a bad idea. It will result in something called shadowing; Basically you have two different "MyInt" members, one in the mother, and the other in the daughter. The problem with this, is that methods that are implemented in the mother will reference the mother's "MyInt" while methods implemented in the daughter will reference the daughter's "MyInt". this can cause some serious readability issues, and confusion later down the line.
Personally, I think the best option is 3; because it provides a clear centralized value, and can be referenced internally by children without the hassle of defining their own fields -- which is the problem with option 1.
You could define something like this:
abstract class Father
{
//Do you need it public?
protected readonly int MyInt;
}
class Son : Father
{
public Son()
{
MyInt = 1;
}
}
By setting the value as readonly, it ensures that the value for that class remains unchanged for the lifetime of the object.
I suppose the next question is: why do you need it?
If you are building a class and you want there to be a base value for the property, then use the virtual keyword in the base class. This allows you to optionally override the property.
Using your example above:
//you may want to also use interfaces.
interface IFather
{
int MyInt { get; set; }
}
public class Father : IFather
{
//defaulting the value of this property to 1
private int myInt = 1;
public virtual int MyInt
{
get { return myInt; }
set { myInt = value; }
}
}
public class Son : Father
{
public override int MyInt
{
get {
//demonstrating that you can access base.properties
//this will return 1 from the base class
int baseInt = base.MyInt;
//add 1 and return new value
return baseInt + 1;
}
set
{
//sets the value of the property
base.MyInt = value;
}
}
}
In a program:
Son son = new Son();
//son.MyInt will equal 2
You can go with option 3 if you modify your abstract base class to require the property value in the constructor, you won't miss any paths. I'd really consider this option.
abstract class Aunt
{
protected int MyInt;
protected Aunt(int myInt)
{
MyInt = myInt;
}
}
Of course, you then still have the option of making the field private and then, depending on the need, exposing a protected or public property getter.
I'd go with option 3, but have an abstract setMyInt method that subclasses are forced to implement. This way you won't have the problem of a derived class forgetting to set it in the constructor.
abstract class Base
{
protected int myInt;
protected abstract void setMyInt();
}
class Derived : Base
{
override protected void setMyInt()
{
myInt = 3;
}
}
By the way, with option one, if you don't specify set; in your abstract base class property, the derived class won't have to implement it.
abstract class Father
{
abstract public int MyInt { get; }
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
}
}
I did this...
namespace Core.Text.Menus
{
public abstract class AbstractBaseClass
{
public string SELECT_MODEL;
public string BROWSE_RECORDS;
public string SETUP;
}
}
namespace Core.Text.Menus
{
public class English : AbstractBaseClass
{
public English()
{
base.SELECT_MODEL = "Select Model";
base.BROWSE_RECORDS = "Browse Measurements";
base.SETUP = "Setup Instrument";
}
}
}
This way you can still use fields.
The example implementation when you want to have an abstract class with implementation. Subclasses must:
Parameterize the implementation of an abstract class.
Fully inherit the implementation of the abstract class;
Have your own implementation.
In this case, the properties that are necessary for the implementation should not be available for use except for the abstract class and its own subclass.
internal abstract class AbstractClass
{
//Properties for parameterization from concrete class
protected abstract string Param1 { get; }
protected abstract string Param2 { get; }
//Internal fields need for manage state of object
private string var1;
private string var2;
internal AbstractClass(string _var1, string _var2)
{
this.var1 = _var1;
this.var2 = _var2;
}
internal void CalcResult()
{
//The result calculation uses Param1, Param2, var1, var2;
}
}
internal class ConcreteClassFirst : AbstractClass
{
private string param1;
private string param2;
protected override string Param1 { get { return param1; } }
protected override string Param2 { get { return param2; } }
public ConcreteClassFirst(string _var1, string _var2) : base(_var1, _var2) { }
internal void CalcParams()
{
//The calculation param1 and param2
}
}
internal class ConcreteClassSecond : AbstractClass
{
private string param1;
private string param2;
protected override string Param1 { get { return param1; } }
protected override string Param2 { get { return param2; } }
public ConcreteClassSecond(string _var1, string _var2) : base(_var1, _var2) { }
internal void CalcParams()
{
//The calculation param1 and param2
}
}
static void Main(string[] args)
{
string var1_1 = "val1_1";
string var1_2 = "val1_2";
ConcreteClassFirst concreteClassFirst = new ConcreteClassFirst(var1_1, var1_2);
concreteClassFirst.CalcParams();
concreteClassFirst.CalcResult();
string var2_1 = "val2_1";
string var2_2 = "val2_2";
ConcreteClassSecond concreteClassSecond = new ConcreteClassSecond(var2_1, var2_2);
concreteClassSecond.CalcParams();
concreteClassSecond.CalcResult();
//Param1 and Param2 are not visible in main method
}

Categories