[英]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 , eg 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 ? 这种情况是否有机会以不同的方式在C#中实现,还是我必须找到另一种设计?
If so what alternatives do you propose ? 如果是这样,你建议用什么替代品?
Thanks in advance for your help. 在此先感谢您的帮助。
Your objective does not make sense. 你的目标没有意义。
Neither ICustomer
nor IEmployee
define a Call()
method; ICustomer
和IEmployee
都没有定义Call()
方法; they just inherit the method from the same interface. 他们只是从同一个接口继承该方法。 Your
Both
class implements the same interface twice. 您的
Both
类两次实现相同的接口。
Any possible Call
call will always call IPerson.Call
; 任何可能的
Call
呼叫将始终呼叫IPerson.Call
; there are no IL instructions that will specifically call ICustomer.Call
or IEmployee.Call
. 没有专门调用
ICustomer.Call
或IEmployee.Call
IL指令。
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. 您可以通过在两个子接口中显式重新定义
Call
来解决此问题,但我强烈建议您只是给它们不同的名称。
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. 以上假设Both类中的Employee是IEmployee的自定义实现,并且是基于Both对象构造的。
But it depends on how you were planning to use the Both class. 但这取决于你打算如何使用Both类。
If you wanted to use the Both class like this: 如果你想像这样使用Both类:
((IEmployee)both).Call();
Then instead you can use this: 然后你可以使用这个:
both.Employee.Call();
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 因此,为了能够多次实现IPerson,在本例中,我将使用泛型,以便能够将IPerson接口从客户拆分为员工
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... 除了SLaks准确指出的问题......
Get rid of IPerson
and create IContactable
with a method of Contact()
, then Create two concrete types called Customer
and Employee
that implement IContactable
. 摆脱
IPerson
并使用Contact()
方法创建IContactable
,然后创建两个实现IContactable
称为Customer
和Employee
具体类型。 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. 然后,当你需要联系某人时,你可以根据需要调用你的
IContactable.Contact()
方法,因为能够进行联系可以扩展,而IPerson
有点抽象。
You can't do this because the Call method comes from the IPerson interface in the two cases. 你不能这样做,因为Call方法来自两种情况下的IPerson接口。 So you try to define the Call method two times.
因此,您尝试两次定义Call方法。 I suggest you to change your ICustomer and IEmployee interface into class and to define the Call method in this class :
我建议您将ICustomer和IEmployee接口更改为类,并在此类中定义Call方法:
interface IPerson
{
void Call();
}
class Customer : IPerson
{
public void Call()
{
}
}
class Employee : IPerson
{
public void Call()
{
}
}
I dont know if this helps or not, but you could get it a shot. 我不知道这是否有帮助,但你可以试一试。
//ran in linqpad c# program mode, you'll need to provide an entry point.....
void Main()
{
IPerson x;
x = new Both(new Employee());
x.call(); //outputs "Emplyee"
x = new Both(new Customer());
x.call(); //outputs "Customer"
}
class Customer : ICustomer
{
public void call() {"Customer".Dump();}
}
class Employee : IEmployee
{
public void call() {"Employee".Dump();}
}
class Both : IPerson
{
private IPerson Person { get; set; }
public Both(IPerson person)
{
this.Person = person;
}
public void call()
{
Person.call();
}
}
interface IPerson { void call(); }
interface ICustomer : IPerson { }
interface IEmployee : IPerson { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.