I have a very simple scenario : a "person" can be a "customer" or an "employee" of a company.
A "person" can be called by phone with the "Call" method.
Depending on which role the "person" plays in the context of the call, e.g. the announcement of a new product or the announcement of a change in organization, we should either use the phone number provided for the "customer" role or the one provided for the "employee" role.
Here is a sum-up of the situation :
interface IPerson
{
void Call();
}
interface ICustomer : IPerson
{
}
interface IEmployee : IPerson
{
}
class Both : ICustomer, IEmployee
{
void ICustomer.Call()
{
// Call to external phone number
}
void IEmployee.Call()
{
// Call to internal phone number
}
}
But this code doe not compile and produces the errors :
error CS0539: 'ICustomer.Call' in explicit interface declaration is not a member of interface
error CS0539: 'IEmployee.Call' in explicit interface declaration is not a member of interface
error CS0535: 'Both' does not implement interface member 'IPerson.Call()'
Does this scenario has any chance to be implementable in C# in a different way or will I have to find another design ?
If so what alternatives do you propose ?
Thanks in advance for your help.
With C# 8.0, you can now have default implementations of methods in an interface. Interface members can be private, protected, and static as well. Protected members of an interface cannot be accessed in the class that extends the interface. Rather, they can be accessed only in the derived interface.
2. Which of the following cannot be used to declare an interface correctly? Explanation: None.
Interface implementation, in C#, refers to the inheritance of an interface by a struct or class that provides the functionality for the members declared in the interface. The members of the implemented interface can include methods, properties, indexers and events.
Answers. By definition of what an interface is it is impossible to return an interface because interfaces cannot be allocated; there cannot be anything to return.
Your objective does not make sense.
Neither ICustomer
nor IEmployee
define a Call()
method; they just inherit the method from the same interface. Your Both
class implements the same interface twice.
Any possible Call
call will always call IPerson.Call
; there are no IL instructions that will specifically call ICustomer.Call
or IEmployee.Call
.
You may be able to solve this by explicitly redefining Call
in both child interfaces, but I highly recommend that you just give them different names.
I'm interested on your input with my solution...
I used explicit implementation a lot with compositions when I want a controller to access some properties or methods on my class that should be hidden from a regular usage of the class...
So, to be able to have multiple implementation of IPerson, in this example, I would use generic, to be able to split the IPerson interface from a customer to an employee
interface IPerson<T>
{
void Call();
}
interface ICustomer : IPerson<ICustomer>
{
}
interface IEmployee : IPerson<IEmployee>
{
}
class Both : ICustomer, IEmployee
{
void IPerson<ICustomer>.Call()
{
// Call to external phone number
}
void IPerson<IEmployee>.Call()
{
// Call to internal phone number
}
}
Aside from the issues SLaks accurately pointed out...
Get rid of IPerson
and create IContactable
with a method of Contact()
, then Create two concrete types called Customer
and Employee
that implement IContactable
. Then whenever you need to contact someone you can call your IContactable.Contact()
method as desired since being able to make contact could expand, whereas IPerson
is a bit abstract.
I ran into this myself.
You can solve the problem by using composition:
interface IPerson
{
void Call();
}
interface ICustomer : IPerson
{
}
interface IEmployee : IPerson
{
}
class Both
{
public ICustomer Customer { get; }
public IEmployee Employee { get; }
}
The above assumes that the Employee in the Both class is a custom implementation of IEmployee, and is constructed based on a Both object.
But it depends on how you were planning to use the Both class.
If you wanted to use the Both class like this:
((IEmployee)both).Call();
Then instead you can use this:
both.Employee.Call();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With