Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit interface implementation limitation

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.

like image 452
Pragmateek Avatar asked Dec 07 '10 17:12

Pragmateek


People also ask

Can we write method implementation in interface C#?

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.

Which of the following Cannot be used to declare an interface in C#?

2. Which of the following cannot be used to declare an interface correctly? Explanation: None.

What is implementation C#?

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.

Can interface methods have return type in C#?

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.


4 Answers

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.

like image 82
SLaks Avatar answered Nov 16 '22 16:11

SLaks


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 
    }
} 
like image 36
crackity_jones666 Avatar answered Nov 16 '22 17:11

crackity_jones666


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.

like image 1
Aaron McIver Avatar answered Nov 16 '22 18:11

Aaron McIver


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();
like image 1
Alex G Avatar answered Nov 16 '22 16:11

Alex G