gpt4 book ai didi

c# - 虚拟调用与类型检查的另一个例子

转载 作者:行者123 更新时间:2023-12-01 20:05:35 24 4
gpt4 key购买 nike

问题

我发誓,每次我脑子里都在想,我应该使用虚拟调用而不是类型检查(例如:

if (obj is Foo)
...
else if (obj is Bar)
...

...我想出了另一个例子,但我不知道如何实现前者。

我正在通过串行端口实现分组协议(protocol)。一些伪代码可以最好地解释这一点:

OnDataReceived:
RcvPacket p = RcvPacket.ReadPacket(comport); // Call factory method
if (p is RcvPacketFoo)
OnFoo();
if (p is RcvPacketBar)
OnBar();

OnFoo:
raise Foo event
OnBar:
raise Bar event

基本上,ReadPacket 是基类中的一个工厂方法,它确定接收到的数据包的类型,并将缓冲区传递给正确的派生类型构造函数。之后,我需要根据数据包的类型引发一个事件。如何在不使用 is 运算符的情况下执行此操作?我的方法合理吗?

<小时/>

解决方案

Visitor Pattern , 当然!谢谢Pablo Romeo .

在本例中,我将调用工厂方法的 Controller 设为访问者。我的结果:

public interface IPacketHandler {
void Handle(FooPacket p);
void Handle(BarPacket p);
}

public class Controller : IPacketHandler {
OnDataReceived() {
RcvPacket p = RcvPacket.ReadPacket(comport); // Call factory method
p.Handle(this); // *** Virtual Call: The first dispatch ***
}

// Note the use of explicit interface implementation here.
IPacketHandler.Handle(FooPacket p) {
OnFoo();
}
IPacketHandler.Handle(BarPacket p) {
OnBar();
}
}

public abstract class RcvPacket {
public static RcvPacket ReadPacket(...) { ... } // Factory method
public void Handle(IPacketHandler handler);
}
public class FooPacket : RcvPacket {
public override void Handle(IPacketHandler handler) {
handler.Handle(this); // *** Overloaded call: The second dispatch ***
}
}
public class BarPacket : RcvPacket {
public override void Handle(IPacketHandler handler) {
handler.Handle(this); // *** Overloaded call: The second dispatch ***
}
}

这里有趣的是,通过显式实现访问者接口(interface),Handle 调用本质上是隐藏的。来自 MSDN :

A class that implements an interface can explicitly implement a member of that interface. When a member is explicitly implemented, it cannot be accessed through a class instance, but only through an instance of the interface.

最佳答案

我能想到的唯一方法是移动 OnFoo 的实现和OnBarRcvPacketFooRcvPacketBar类。

public class RcvPacket{
public abstract void On(RcvPacketHandler eh);
}
public class RcvPacketFoo : RcvPacket
{
public override void On(RcvPacketHandler eh){eh.OnFoo();} //OnFoo implemenation
}

public class RcvPacketBar : RcvPacket
{
public override void On(RcvPacketHandler eh){eh.OnBar();} //OnBar implemenation
}
//Update following your comment:
public class RcvPacketHandler
{
public void OnFoo(){}
public void OnBar(){}
//....
OnDataReceived:
RcvPacket p = RcvPacket.ReadPacket(comport); // Call factory method
p.On(this);

关于c# - 虚拟调用与类型检查的另一个例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10746417/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com