Why not override get-only property with settable property? - c#

Overriding get-only property with settable property is prohibited in C#.
public class Example : IExample //// OR ExampleBase
{
public int Property { get; set; } //// This causes error.
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
I've already checked question 1 and question 2.
I know how to avoid the error, but I don't know why this should be prohibited.
Please let me know why overriding get-only property with settable property is wrong.

TL;DR;
Overriding or implementing get-only property with settable property is prohibited in C#.
Partially correct. It's perfectly valid to implement a get-only property with a settable property - but it's invalid to override a get-only property with a settable property.
The long version:
When I've tried to compile your code, I've got two compilation errors (In VS 2017, if that matters)
Error CS0106 The modifier 'abstract' is not valid for this item
Error CS0106 The modifier 'public' is not valid for this item
When removed the public abstract from the property in the interface, the code compiles just fine (removed the abstract class as it's irrelevant here):
public class Example : IExample
{
public int Property { get; set; }
}
public interface IExample
{
int Property { get; }
}
However, when attempting to use an abstract class and override a get only property with a get/set property, I got this compilation error:
Error CS0546 'Example.Property.set': cannot override because 'ExampleBase.Property' does not have an overridable set accessor
for the following code (removed the interface, same error for a private set):
public class Example : ExampleBase
{
public override int Property { get; set; }
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
This is actually a good way to show the difference between overriding and implementing in c#:
An interface is a contract. It force the implementing types to include it's members as a part of it's public API (explicit implementation aside). So when implementing an interface with a get-only property, you can add a setter to this property, because as long as it has the getter, the contract is still being fulfilled.
However, a base class is not a contract. If forces the inheriting classes to have the exact same member signature, but allows the inheriting class to override virtual members (so the same method or property will be implemented differently in the two classes). In fact, a derived class is a (specific) type of it's base class.
Usually If you want to add a setter to a get-only property in the base class, you will have to shadow it using the keyword new, but this will not help with abstract members - an abstract member must be overriden in the derived class - and since we don't have properties overloads, you will have to add a method to set the value of the get-only property, and implement it explicitly:
public class Example : ExampleBase
{
private int _property;
public override int Property { get { return _property; } }
public void SetProperty(int property)
{
_property = property;
}
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
And for the sake of completeness - here is how you would use the new keyword if the base property was not abstract:
public class Example : ExampleBase
{
public new int Property { get; set; }
}
public class ExampleBase
{
public virtual int Property { get; }
}

The abstract and public modifiers are not available in an interface.
Assuming you meant the following:
public class Example : ExampleBase
{
public override int Property { get; set; } //// This causes error.
//// public int Property { get; private set; } //// This causes error, too.
}
public interface IExample
{
int Property { get; }
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
When you implement an interface (IExample) you can add a setter. When you extend the abstract class (ExampleBase) you have to implement the property the way the abstract base specifies it must be implemented, that is with just a getter.

I can't speak in place of the C# language team but to me I think it comes to consistency and avoiding design mistake.
While the CLR doesn't forbid it - you could think a property as a pair of GetProperty() and SetProperty() methods, for which one could be defined in the base class and the other in a derived class - when bundled into a property you are basically expressing a contract to access a "resource" (usually a field).
So when the base class declares a property to be getter only, you don't expect concrete implementation to expose a setter in the same place. If the concrete class does need to so, then it better conveys its intent by defining a separate method, since it is kind of "breaking" the class contract.
When it comes to interface, on the other hand, the contract is only on a "surface" API: just just say that method or that getter must be implemented. And you could have one interface defining get-only properties and one interface defining set-only properties (why not).

Related

Concrete class which inherites a generic interface

I want to have a generic interface which has a property that is the used as the Id property of the derived classes.
I wrote the interface like below:
interface IEntity<T>
{
T Id { get; set; }
}
and the derived classes can use it like below:
public class Employee : IEntity<int>
{
// don't need to define Id property
// public int Id { get; set; }
}
public class Document : IEntity<string> { ... }
Unfortunately, the compiler nags this error:
'Employee' does not implement interface member 'IEntity.Id'
What did i do wrong? thanks.
Edit:
While the accepted answer solves the problem, the #dbc comments helped me to achieve my goal, if i changed the interface IEntity to abstract class IEntity it doesn't need to implement the Id property in the derived class.
You are confusing inheritance and interface implementation.
When an interface inherits another interface, the members are inherited, and you do not repeat them:
interface IEntity<T>
{
T Id { get; set; } // necessary code for 'get' and 'set' not present (yet)
}
interface IEmployee : IEntity<int>
{
// don't need to repeat Id property
// it is inherited
}
Similarly when a class inherits another class:
class Entity<T>
{
public T Id { get; set; } // automatic code for 'get' and 'set' exists here
}
class Employee : Entity<int>
{
// don't need to repeat Id property
// it is inherited
}
The base class may be made abstract if you want to make sure only derived classes are instantiated.
But when a class (or a struct) implements and interface, every member of the interface must be implemented in some way. Usually by a public member of that class or struct. (That public member may be inherited from a base class!) Or, occasionally, by an explicit interface implementation.
An interface has no bodies, just signatures. For example the get and set accessors of the Id property must have some body to make sense. When you write T Id { get; set; } in an interface, there are no bodies of the accessors. But when you write T Id { get; set; } in a class (or struct), and there is no abstract or extern modifier, the semicolons have another meaning; then the compiler while auto-generate the necessary accessor bodies (and also auto-generate a field which is used by the accessors).
As in interface, ALL methods must be implemented!
Properties are nothing more than just methods, which have to be implemented when defined in interface: int Id { get; set; }.
You need to implement interface for every class - just like mentioned earlier:
interface IEntity<T>
{
T Id { get; set; }
}
public class Employee : IEntity<int>
{
public int Id { get; set; }
}

Interface inheritance in c#: property does not inherit get accessor [duplicate]

This question already has answers here:
Adding setter to inherited read-only property in C# interface
(3 answers)
Closed 6 years ago.
Consider the following code:
public interface IFoo
{
int Bar { get; }
}
public interface IModifiableFoo : IFoo
{
int Bar { set; }
}
public class FooImpl : IModifiableFoo
{
public int Bar { get; set; }
}
static void Main()
{
IModifiableFoo f = new FooImpl();
int bar = f.Bar; // Compiler error
}
This is the error message:
error CS0154: The property or indexer 'MyNamespace.IModifiableFoo.Bar' cannot be used in this context because it lacks the get accessor
Since IModifiableFoo inherits IFoo, the get accessor (i.e. get_Bar() method) should be accessible. What is going on here?
Note: This is different from question Adding setter to inherited read-only property in C# interface because that question does not address compiler error in calling getter via writable interface.
The reason is that your IModifiableFoo interface's property hides the one it gets inherited from IFoo, instead of overriding it. So if you want your get functionality in your derived interface, you have to explicitly add it.
Actually, you'd better mark your Bar property in IModifiableFoo with new keyword, to explicitly show that it hides something behind, in order to not get confused when looking up the code.
Getters and setters are not individual members. So a setter in one interface does not add to the getter of the base interface. Instead, interfaces only define members, and that member here is either a readable or writable property.
The inheriting interface defines a property (a member) with the same name as the base interface. So it will hide the base interface’s member. So with two interfaces, you now have two members you could explicitly implement:
int IFoo.Bar { get; }
int IModifiableFoo.Bar { set; }
Note that the compiler should give you a warning about this behavior, and advises you to use the new keyboard in the inheriting interface to mark this as intentional:
public interface IModifiableFoo : IFoo
{
new int Bar { get; set; }
}
Don't use properties and interface inheritance here. Use regular methods and two separate interfaces:
public interface IFooReader
{
int GetBar();
}
public interface IFooWriter
{
void SetBar(int value);
}
public class FooImpl : IFooReader, IFooWriter
{
public int GetBar() { /* ... */ }
public void SetBar(int value) { /* ... */ }
}

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.

Accessibility of abstract properties

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

Categories