【发布时间】:2022-01-23 14:26:34
【问题描述】:
在基础知识方面摸不着头脑。
我有几个(例如)消息类共享一个公共基类。我有一个接受基类作为参数的接口。到目前为止,我认为可以很容易地使用方法重载来处理单独方法中的特定类型的消息。
您如何运行以下示例:
using System;
namespace MethodOverloading
{
// for the example: we are sending messages
// which have a common base class
public class MessageBase
{
public readonly string Value;
public MessageBase() { Value = GetType().Name; }
}
// and there are a couple of concrete instances
public class Message1000 : MessageBase { }
public class Message2000 : MessageBase { }
public class Message3000 : MessageBase { }
public class Message4000 : MessageBase { }
public class Message5000 : MessageBase { }
// and of cource we have an interface receiving all messages but only with one method for the base defined
public interface IHandler
{
void ReceiveMessage(MessageBase msg);
}
// the handlers should do some method overloading so a overloaded method can be implemented for each supported message
// and the base message catches all unsupported messages (e.g. log: ey, missed an overload for this type)
// Handler 1 tries to overload the interface method
public class Handler1 : IHandler
{
public void ReceiveMessage(MessageBase msg) { Console.WriteLine($"Handler1.ReceiveMessage(MessageBase:{msg.Value})"); }
public void ReceiveMessage(Message1000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message1000:{msg.Value})"); }
public void ReceiveMessage(Message2000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message2000:{msg.Value})"); }
public void ReceiveMessage(Message3000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message3000:{msg.Value})"); }
public void ReceiveMessage(Message4000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
// Handler 2 provides one interface method and has protected overloads...
public class Handler2 : IHandler
{
public void ReceiveMessage(MessageBase msg)
{
Console.Write($"Handler2.ReceiveMessage(MessageBase:{msg.Value}) > ");
HandleMessage(msg);
}
protected void HandleMessage(MessageBase msg) { Console.WriteLine($"Handler2.HandleMessage(MessageBase:{msg.Value})"); }
protected void HandleMessage(Message1000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message1000:{msg.Value})"); }
protected void HandleMessage(Message2000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message2000:{msg.Value})"); }
protected void HandleMessage(Message3000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message3000:{msg.Value})"); }
protected void HandleMessage(Message4000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
class Program
{
static void Main(string[] args)
{
// so lets give it a try ....
Console.WriteLine("Testing method overloads");
MessageBase msgBase = new MessageBase();
Message1000 msg1000 = new Message1000();
Message2000 msg2000 = new Message2000();
Message3000 msg3000 = new Message3000();
Message4000 msg4000 = new Message4000();
Message5000 msg5000 = new Message5000();
Console.WriteLine("Handler1:");
Handler1 handler1 = new Handler1();
handler1.ReceiveMessage(msgBase);
handler1.ReceiveMessage(msg1000);
handler1.ReceiveMessage(msg2000);
handler1.ReceiveMessage(msg3000);
handler1.ReceiveMessage(msg4000);
handler1.ReceiveMessage(msg5000);
Console.WriteLine("iHandler1:");
IHandler ihandler1 = new Handler1();
ihandler1.ReceiveMessage(msgBase);
ihandler1.ReceiveMessage(msg1000);
ihandler1.ReceiveMessage(msg2000);
ihandler1.ReceiveMessage(msg3000);
ihandler1.ReceiveMessage(msg4000);
ihandler1.ReceiveMessage(msg5000);
Console.WriteLine("Handler2:");
Handler2 handler2 = new Handler2();
handler2.ReceiveMessage(msgBase);
handler2.ReceiveMessage(msg1000);
handler2.ReceiveMessage(msg2000);
handler2.ReceiveMessage(msg3000);
handler2.ReceiveMessage(msg4000);
handler2.ReceiveMessage(msg5000);
Console.WriteLine("iHandler2:");
IHandler ihandler2 = new Handler2();
ihandler2.ReceiveMessage(msgBase);
ihandler2.ReceiveMessage(msg1000);
ihandler2.ReceiveMessage(msg2000);
ihandler2.ReceiveMessage(msg3000);
ihandler2.ReceiveMessage(msg4000);
ihandler2.ReceiveMessage(msg5000);
Console.WriteLine("press any key to exit");
Console.ReadLine();
}
}
}
输出实际上是:
Testing method overloads
Handler1:
Handler1.ReceiveMessage(MessageBase:MessageBase)
Handler1.ReceiveMessage(Message1000:Message1000)
Handler1.ReceiveMessage(Message2000:Message2000)
Handler1.ReceiveMessage(Message3000:Message3000)
Handler1.ReceiveMessage(Message4000:Message4000)
Handler1.ReceiveMessage(MessageBase:Message5000)
iHandler1:
Handler1.ReceiveMessage(MessageBase:MessageBase)
Handler1.ReceiveMessage(MessageBase:Message1000)
Handler1.ReceiveMessage(MessageBase:Message2000)
Handler1.ReceiveMessage(MessageBase:Message3000)
Handler1.ReceiveMessage(MessageBase:Message4000)
Handler1.ReceiveMessage(MessageBase:Message5000)
Handler2:
Handler2.ReceiveMessage(MessageBase:MessageBase) > Handler2.HandleMessage(MessageBase:MessageBase)
Handler2.ReceiveMessage(MessageBase:Message1000) > Handler2.HandleMessage(MessageBase:Message1000)
Handler2.ReceiveMessage(MessageBase:Message2000) > Handler2.HandleMessage(MessageBase:Message2000)
Handler2.ReceiveMessage(MessageBase:Message3000) > Handler2.HandleMessage(MessageBase:Message3000)
Handler2.ReceiveMessage(MessageBase:Message4000) > Handler2.HandleMessage(MessageBase:Message4000)
Handler2.ReceiveMessage(MessageBase:Message5000) > Handler2.HandleMessage(MessageBase:Message5000)
iHandler2:
Handler2.ReceiveMessage(MessageBase:MessageBase) > Handler2.HandleMessage(MessageBase:MessageBase)
Handler2.ReceiveMessage(MessageBase:Message1000) > Handler2.HandleMessage(MessageBase:Message1000)
Handler2.ReceiveMessage(MessageBase:Message2000) > Handler2.HandleMessage(MessageBase:Message2000)
Handler2.ReceiveMessage(MessageBase:Message3000) > Handler2.HandleMessage(MessageBase:Message3000)
Handler2.ReceiveMessage(MessageBase:Message4000) > Handler2.HandleMessage(MessageBase:Message4000)
Handler2.ReceiveMessage(MessageBase:Message5000) > Handler2.HandleMessage(MessageBase:Message5000)
press any key to exit
处理程序 1 在直接调用时实际上可以工作。不幸的是,作为接口调用时不是开箱即用的。
虽然我认为至少带有受保护重载的 Handler2 可以解决问题....
我实际上想要摆脱的是在 Handler3 中带有强制转换的 switch 语句(因为很容易错过额外的步骤,并且在开发人员无法访问的基类中实现这种魔力会很棒):
public class Handler3 : IHandler
{
public void ReceiveMessage(MessageBase msg)
{
Console.Write($"Handler3.ReceiveMessage(MessageBase:{msg.Value}) > ");
switch (msg)
{
case Message1000 msg1000: HandleMessage(msg1000); break;
case Message2000 msg2000: HandleMessage(msg2000); break;
case Message3000 msg3000: HandleMessage(msg3000); break;
case Message4000 msg4000: HandleMessage(msg4000); break;
default: Console.WriteLine("dropped because not supported: " + msg.Value); break; // for the msg5000
}
}
//protected void HandleMessage(MessageBase msg) { Console.WriteLine($"Handler3.HandleMessage(MessageBase:{msg.Value})"); }
protected void HandleMessage(Message1000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message1000:{msg.Value})"); }
protected void HandleMessage(Message2000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message2000:{msg.Value})"); }
protected void HandleMessage(Message3000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message3000:{msg.Value})"); }
protected void HandleMessage(Message4000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
实际效果如输出所示:
Handler3:
Handler3.ReceiveMessage(MessageBase:MessageBase) > dropped because not supported: MessageBase
Handler3.ReceiveMessage(MessageBase:Message1000) > Handler3.HandleMessage(Message1000:Message1000)
Handler3.ReceiveMessage(MessageBase:Message2000) > Handler3.HandleMessage(Message2000:Message2000)
Handler3.ReceiveMessage(MessageBase:Message3000) > Handler3.HandleMessage(Message3000:Message3000)
Handler3.ReceiveMessage(MessageBase:Message4000) > Handler3.HandleMessage(Message4000:Message4000)
Handler3.ReceiveMessage(MessageBase:Message5000) > dropped because not supported: Message5000
但如果您错过使用该变体的方法重载,编译器会抱怨并阻止构建,这是一个好处。
【问题讨论】:
标签: c# overloading