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
}
Related
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).
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; }
}
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) { /* ... */ }
}
I have class MockRepository which implements interface IRepository and I have a class Technology which implements interface IIdentifiable.
I want to cast an object from MockRepository<Technology> to IRepository<IIdentifiable> and also cast back again after some operations are complete. Is this possible? my code compiles but when i try to run it i get an invalid cast exception.
Short answer is no.
If you have an interface IMyInterface<T> then the compiler will create a new interface for each type of T that you use and substitute for all values of T.
To give an example:
I have an interface:
public interface IMyInterface<T> {
public T Value {get; set;}
}
I have 2 classes:
public class Foo {}
public class Bar : Foo {}
I then define the following
public class Orange : IMyInterface<Foo> {}
public class Banana : IMyInterface<Bar> {}
The compiler will automatically create 2 new interfaces using a specific name convention, I'm going to use different names to highlight that they are different
public interface RandomInterface {
Foo Value { get; set; }
}
public interface AlternativeInterface {
Bar Value { get; set; }
}
public class Orange : RandomInterface {
}
public class Banana : AlternativeInterface {
}
As you can see there is no relationship between RandomInterface and AlternativeInterface. So a class inheriting from RandomInterface cannot be cast to AlternativeInterface
UPDATE AFTER READING QUESTION COMMENTS
If you wish to pass MockRepository to a function that expects IRepository you can do the following
public void MyFunction<T>(IRepository<T> repo) where T: IIdentifiable {
}
I take it you have:
class MockRepository<T> : IRepository<T> // note: same T
{
}
interface IRepository<out X> // note: "out" means covariance in X
{
}
Then because a Technology is an IIdentifiable, covariance gives that an IRepository<Technology> is also an IRepository<IIdentifiable>.
So if your IRepository<> interface is (or can be made) covariant, it should work.
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.