显式接口实现限制

发布于 2024-10-06 11:17:22 字数 1096 浏览 2 评论 0原文

我有一个非常简单的场景:“”可以是公司的“客户”或“员工”。

可以使用“呼叫”方法通过电话呼叫“”。

根据“人员”在通话上下文中扮演的角色,例如新产品的公告或组织变更的公告,我们应该使用为“客户”角色提供的电话号码或为“员工”角色提供的电话号码。

以下是情况的总结:

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
    }
}

但是此代码无法编译并产生错误:

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()'

此场景是否有机会以不同的方式在 C# 中实现,还是我必须找到另一种设计?

如果是这样,您建议什么替代方案?

提前感谢您的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷默言语 2024-10-13 11:17:22

你的目标没有意义。

ICustomerIEmployee 都没有定义 Call() 方法;他们只是从同一个接口继承方法。您的 Both 类两次实现相同的接口。
任何可能的 Call 调用都将始终调用 IPerson.Call;没有专门调用 ICustomer.CallIEmployee.Call 的 IL 指令。

您也许可以通过在两个子接口中显式重新定义Call 来解决此问题,但我强烈建议您为它们指定不同的名称。

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.

冷弦 2024-10-13 11:17:22

我对您对我的解决方案的输入感兴趣...

当我希望控制器访问我的类上的某些属性或方法时,我在组合中使用了很多显式实现,而这些属性或方法应该在类的常规使用中隐藏...

所以,为了能够有 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 
    }
} 

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 
    }
} 
岁月蹉跎了容颜 2024-10-13 11:17:22

除了 SLAks 准确指出的问题之外...

摆脱 IPerson 并使用 Contact() 方法创建 IContactable,然后创建两个名为 CustomerEmployee 的具体类型实现了 IContactable。然后,每当您需要联系某人时,您都可以根据需要调用 IContactable.Contact() 方法,因为联系能力可以扩展,而 IPerson 有点抽象。

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.

似狗非友 2024-10-13 11:17:22

我自己也遇到过这个。

可以通过组合的方式来解决这个问题:

interface IPerson
{
    void Call();
}

interface ICustomer : IPerson
{
}

interface IEmployee : IPerson
{
}

class Both
{
    public ICustomer Customer { get; }
    public IEmployee Employee { get; }
}

上面假设Both类中的Employee是IEmployee的自定义实现,并且是基于Both对象构造的。

但这取决于您计划如何使用 Both 类。
如果你想像这样使用 Both 类:

((IEmployee)both).Call();

那么你可以使用这个:

both.Employee.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.

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();
↙温凉少女 2024-10-13 11:17:22

您不能这样做,因为在这两种情况下 Call 方法来自 IPerson 接口。所以你尝试定义两次 Call 方法。
我建议您将 ICustomer 和 IEmployee 接口更改为类,并在此类中定义 Call 方法:

interface IPerson
{
    void Call();
}

class Customer : IPerson
{
    public void Call()
    {
    }
}

class Employee : IPerson
{
    public void Call()
    {
    }
}

You can't do this because the Call method comes from the IPerson interface in the two cases. So you try to define the Call method two times.
I suggest you to change your ICustomer and IEmployee interface into class and to define the Call method in this class :

interface IPerson
{
    void Call();
}

class Customer : IPerson
{
    public void Call()
    {
    }
}

class Employee : IPerson
{
    public void Call()
    {
    }
}
神妖 2024-10-13 11:17:22

我不知道这是否有帮助,但你可以尝试一下。

//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 { } 

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 { } 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文