How to override a getter-only property with a setter in C#?
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.
Override get, but not set
New in C# 6.0:
If you are only calling the setter within your constructor, you can resolve this problem using read-only properties.
void Main()
{
BaseClass demo = new DClass(3.6);
}
public abstract class BaseClass
{
public abstract double MyPop{ get; }
}
public class DClass : BaseClass
{
public override double MyPop { get; }
public DClass(double myPop) { MyPop = myPop;}
}
Why can a full property in C# be overridden with only a getter but it can still be set?
I'll take a crack at this.
It looks like this may just be a bug with Intellisense, where it is unable to find the base implementation of an auto-property. The code is valid and makes sense - here's another way to express your example.
Child child = new Child();
child.SetProperty(true);
class Parent
{
private bool _property;
public virtual bool GetProperty() => _property;
public virtual void SetProperty(bool value) => _property = value;
}
class Child : Parent
{
public override bool GetProperty() => base.GetProperty();
}
With this representation, it's now obvious why overriding GetProperty is fine. Here's the relevant IL for your code:
Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.set_Property
IL_000B: ret
Parent.get_Property:
IL_0000: ldarg.0
IL_0001: ldfld Parent.<Property>k__BackingField
IL_0006: ret
Parent.set_Property:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent.<Property>k__BackingField
IL_0007: ret
Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
Child.get_Property:
IL_0000: ldarg.0
IL_0001: call Parent.get_Property
IL_0006: ret
Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret
And here's my version:
Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.SetProperty
IL_000B: ret
Parent.GetProperty:
IL_0000: ldarg.0
IL_0001: ldfld Parent._property
IL_0006: ret
Parent.SetProperty:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent._property
IL_0007: ret
Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
Child.GetProperty:
IL_0000: ldarg.0
IL_0001: call Parent.GetProperty
IL_0006: ret
Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret
Note that this is different than public override bool Property { get; }
, being shorthand for instructing the compiler to generate a single getter override for a backing property of the same name, with no mention of the preexisting setter. Somebody experienced with the actual spec will definitely be able to offer more information around this, however.
Override both getter and setter of a property
From my observations, I think you are supposed to use the @Base.value.setter (or .getter) decorator if only the setter (or getter) needs to be overwritten.
If you have to override both, just use the usual @property approach.
class Base():
def __init__(self):
self._value = 'Value'
@property
def value(self):
print('Base.Getter')
return f'Base.{self._value}'
@value.setter
def value(self, value):
print('Base.Setter')
self._value = value
class Child(Base):
@property
#@Base.value.getter
def value(self):
print('Child.Getter')
return f'Child.{self._value}'
@value.setter
#@Base.value.setter
def value(self, value):
print('Child.Setter')
self._value = value
b, c = Base(), Child()
print(b.value)
print(c.value)
b.value = 'test.base'
c.value = 'test.child'
print(b.value)
print(c.value)
prints:
Base.Getter
Base.Value
Child.Getter
Child.Value
Base.Setter
Child.Setter
Base.Getter
Base.test.base
Child.Getter
Child.test.child
Override a setter, and the getter must also be overridden
Yes, this is intentional (a part of the spec). If an object has an own property (.property
in your example), this property will be used and not an inherited one. If that property is existent, but is an accessor property without a getter, then undefined
will be returned.
Notice that this behaviour has not changed from ES5.
Adding setters to properties in overrides
The interface declares what public properties the class must have (It's just a contract). Which means you need to have those properties, but can add to them.
The abstract class declares the actual structure of those properties. So if you don't have the setter in the abstract base, you can't add to it in the implementation.
When you write the override modifier it looks in the base class for something to override.
Overriding a Get/Set Property to Be Get-Only Still Lets You Set It
By looking at the generated CIL code, it turns out that your are overriding the getter method by makking it read only in the derived class:
public override bool Property => property;
but still inheriting the setter, so when you set the property, you still have access to the setter method of the base class.
How do I override the setter method of a property in C#?
The override is fine. However, as the error message states, you need to mark the property in the base class as virtual to be able to override it:
public virtual Vector2 Position
Unlike Java, class members are not virtual by default in C#. If you can't change the base class, you're out of luck.
Related Topics
Ef Code First - How to Set Identity Seed
How to Make a Background Worker Thread Set to Single Thread Apartment
How to Use Httpwebrequest to Pull Image from Website to Local File
Generate N Random and Unique Numbers Within a Range
Does Garbage Collection Run During Debug
How Math.Pow (And So On) Actually Works
End of Central Directory Record Could Not Be Found
How to Keep Console Window Open
C#: Multiline Text in Datagridview Control
Any Reason to Use Auto-Implemented Properties Over Manual Implemented Properties
System.Web.Httpcontext.Current.User.Identity.Name VS System.Environment.Username in ASP.NET
How to Save Picturebox.Image to File
Sqldatasourceenumerator.Instance.Getdatasources() Does Not Locate Local SQL Server 2008 Instance
Implementing Hoey Shamos Algorithm with C#
Badimageformatexception When Loading 32 Bit Dll, Target Is X86
Double.Tryparse or Convert.Todouble - Which Is Faster and Safer