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; }
}
Related
my question is, if you have a method of the form:
public bool ProcessAggregation(IAggregatePoint point) { #do stuff }
And a class, NetworkAggregation, implementing IAggregatePoint. Can you call the method like:
ProcessAggregation(point) where point here is a NetworkAggregation instance?
Also, if not possible with interfaces, could inheritance of an abstract base class work? Meaning any object inheriting from the abstract base class would be passible into the method?
I am reluctant to alter the classes with inheritance as they are database schemas for a MySql database/ used with EntityFramework.
Thanks!
Network aggregation is implemented like:
public class NetworkAggregation : IAggregatePoint
{
public DateTime? AssessmentDate {get; set;}
public int Id {get; set;}
public string DUPValue {get; set;}
//And so on, other properties not specified in IAggregatePoint
}
and IAggregatePoint is implemented like:
public interface IAggregatePoint
{
public DateTime? AssessmentDate {get; set;}
}
Yes, this will work. As long as a class implements the IAggregatePoint interface, an instance of that class can be provided to ProcessAggregation without any issues. You'll get a compiler error if you make a mistake (like trying to use a method that is from NetworkAggregation but not part of IAggregatePoint within ProcessAggregation).
You could also do the same thing with an abstract base class, as you mentioned.
It might be worthwhile to review the C# language specification's documentation on interfaces.
Edit - here's a simple, working example:
public interface IAggregatePoint
{
}
public class NetworkAggregation : IAggregatePoint
{
}
public class AnotherAggregation
{
}
public void Test()
{
// works because NetworkAggregation implements IAggregatePoint
ProcessAggregation(new NetworkAggregation());
// fails to compile (as expected) because AnotherAggregation
// doesn't implement IAggregatePoint
ProcessAggregation(new AnotherAggregation());
}
Here I have two situations:
First situation: class PrattWhitney implements two separate interfaces: IBoeing and IAirbus
Second situation: class PrattWhitney implements IBoeing and IAirbus and IArbus inherits IBoeing
I both cases I have an auto-implemented property impl in both interfaces.
In the first situation, which interface does the PrattWhitney.impl property implement - IBoeing or IAirbus?
And in the second situation, which interface does the PrattWhitney.impl property implement - IBoeing or IAirbus?
First situation:
interface IBoeing
{
int impl { get; set; }
}
interface IAirbus
{
int impl { get; set; }
}
class PrattWhitney : IBoeing, IAirbus
{
public int impl { get; set; }
}
Second situation:
interface IBoeing
{
int impl { get; set; }
}
interface IAirbus : IBoeing
{
int impl { get; set; }
}
class PrattWhitney : IBoeing, IAirbus
{
public int impl { get; set; }
}
In both cases, PrattWhitney.impl implements the impl declared in both interfaces.
You can reason about it this way:
you wrote class PrattWhitney : IBoeing, IAirbus
you wrote only one property called impl
class PrattWhitney : IBoeing, IAirbus wouldn't compile if PrattWhitney doesn't actually implement both of those interfaces
your code compiles
therefore the single property you wrote must have matched both IBoeing.impl and IAirbus.impl
As specified in the language spec,
A class or struct shall provide implementations of all members of the
interfaces that are listed in the base class list of the class or
struct. The process of locating implementations of interface members
in an implementing class or struct is known as interface mapping.
Interface mapping for a class or struct C locates an implementation
for each member of each interface specified in the base class list of
C. The implementation of a particular interface member I.M, where I is
the interface in which the member M is declared, is determined by
examining each class or struct S, starting with C and repeating for
each successive base class of C, until a match is located:
[...]
The language is designed to go over each interface member, and look for an implementation for each of them, rather than go over the members of the class, and look for an interface member for it to implement. It also doesn't matter if the implementation is already used to implement another interface member. Therefore, it can find the same PrattWhitney.impl to implement both IBoeing.impl and IAirbus.impl.
I should mention that the additional inheritance in the second situation doesn't change anything substantial in the context of your question - you still have IBoeing.impl and IAirbus.impl, and PrattWhitney.impl implements both for the same reason. Note that the impl declared in IAirBus hides the inherited impl, as specified here.
The inherited members of an interface are specifically not part of the
declaration space of the interface. Thus, an interface is allowed to
declare a member with the same name or signature as an inherited
member. When this occurs, the derived interface member is said to hide
the base interface member. Hiding an inherited member is not
considered an error, but it does cause the compiler to issue a
warning. To suppress the warning, the declaration of the derived
interface member shall include a new modifier to indicate that the
derived member is intended to hide the base member. This topic is
discussed further in ยง7.7.2.3.
Though I don't see why something called PrattWhitney should implement something called IBoeing and IAirBus, if you would like different implementations for the interfaces, you can use explicit interface implementations:
class PrattWhitney : IBoeing, IAirbus {
int IAirbus.impl {
get { ... }
set { ... }
}
int IBoeing.impl {
get { ... }
set { ... }
}
}
This will make it not possible to access impl on an expression of type PrattWhitney. If you want to do that, you can make one of them an implicit implementation:
class PrattWhitney : IBoeing, IAirbus {
int IAirbus.impl {
get { ... }
set { ... }
}
public int impl {
get { ... }
set { ... }
}
}
First situation:
class PrattWhitney : IBoeing, IAirbus
{
// This property implements both `IAirbus.impl` and `IBoeing.impl`.
public int impl { get; set; }
}
Second situation:
interface IBoeing
{
int impl { get; set; }
}
interface IAirbus : IBoeing
{
// / The missing "new" keyword is treated as warning.
// | See: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords
// V
new int impl { get; set; }
}
class PrattWhitney : IBoeing, IAirbus
{
// This property implements both `IAirbus.impl` and `IBoeing.impl`.
public int impl { get; set; }
}
If you want implement property/method with same signature but from different interfaces you can explicitly implement them (see docs).
class PartWhitney : IBoeing, IAirbus {
int IAirbus.impl { get; set; } = 5
int IBoeing.impl { get; set; } = 7
}
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).
How does .Net ProtoBuf 's ProtoMember work in the inheritance chain? For example, look at the following classes.
[ProtoContract]
public class BaseClass
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
}
[ProtoContract] //required?
public class DerivedClass : BaseClass
{
[ProtoMember(3)] //can tag value be 1 ?
public string Category { get; set; }
}
Questions are mentioned in the code inline.
(1) Do I need to mark the derived class ProtoContract if base class is already ProtoContract?
(2) For properties of derived class, can I reuse tag values (int) of ProtoMember already used in base class properties?
(1) Do I need to mark the derived class ProtoContract if base class is already ProtoContract?
Yes, but You also should set order to deriver type
(2) For properties of derived class, can I reuse tag values (int) of ProtoMember already used in base class properties? yes, You can start from 1 in derived class
I am trying to figure out a way to force all of my Interfaces to include properties of the same name/type.
For example: I have two Interfaces; IGetAlarms and IGetDiagnostics. Each of the Interfaces will contain properties that are specific to the Interface itself, however I want to force the two Interfaces (and all other Interfaces that may be added later) to include properties of the same name. So, the result may look something like the this:
interface IGetAlarms
{
string GetAlarms();
DateTime LastRuntime { get; set; }
}
interface IGetDiagnostics
{
string GetDiagnostics();
DateTime LastRuntime { get; set; }
}
Notice that both Interfaces include a DateTime property named LastRuntime.
I would like to know if there is some way I can force other Interfaces that will be added later to include the DateTime LastRuntime property. I have naively attempted to have all my Interfaces implement another Interface (IService) - which includes the LastRuntime property. However, that doesn't solve my problem as that simply forces the class to implement the property - not all the Interfaces.
Thanks.
An interface can inherit from other interfaces.
interface IDerived : IBase
{
string Foo { get; set; }
}
interface IBase
{
DateTime LastRunDate { get; set; }
}
Any class deriving from IDerived will have to implement the methods/properties of IBase as well.
class Derived : IDerived
{
#region IDerived Members
public string Foo { get; set; }
#endregion
#region IBase Members
public DateTime LastRunDate {get;set;}
#endregion
}
If I understand your question correctly, you want to force a class to implement a number of different interfaces, the list of interfaces will grow with time but will have some properties in common.
The common property part you have solved with your IService interface. Something like this, I presume
interface IService
{
DateTime LastRuntime { get; set; }
}
interface IGetAlarms : IService
{
string GetAlarms();
}
interface IGetDiagnostics : IService
{
string GetDiagnostics();
}
The growing list of interfaces that a class will have to implement you can also solve in a similar fashion. Create a "composite" interface which inherits from all the interfaces you wish your class to implement
interface IComposite : IGetAlarms, IGetDiagnostics {}
class MyClass : IComposite
{
...
}
When you let the IComposite interface inherit a new interface, the class will have implement the new interface too.
EDIT
In response to your clarification; in that case you should not share the specification of the LastRuntime property, but declare it in each individual interface. In the implementing class you can use Explicit interface member implementation
class MyClass : IComposite
{
DateTime IGetAlarms.LastRuntime { get; set; }
DateTime IGetDiagnostics.LastRuntime { get; set; }
...
}
However, AFAIK it is not possible to force the implementing class to explicitly implement each individual interface
It really depends on exactly what you need the interface for. You can use generics to enforce the implementation of a specified pattern, but you can't enforce the implementation of each individually if they all have identical signatures.
public interface IA<T> where T: class
{
void DoIt(T ignore = null);
}
public interface IB : IA<IB>
{
}
public interface IC : IA<IC>
{
}
That would force the following class to implement each separately:
public class D : IB, IC
{
public void DoIt(IB ignore = null) { }
public void DoIt(IC ignore = null) { }
}
It's the "T ignore" parameter that forces each one to be implemented separately, and since it has a default value, you can just ignore that parameter unless calling it using reflection.
But obviously this doesn't work with properties, so they would have to be implemented using getter/setter methods.