首先发布代码会更容易,然后问我为什么会收到此错误。
abstract class Packet
{
// base class!
}
public sealed class FirstPacket : Packet
{
// First packet implementations...
}
public sealed class AnotherPacket : Packet
{
// Another packet implementations...
}
public enum OpCode
{
FirstPacket,
AnotherPacket
}
public abstract class BaseConnection
{
private Dictionary<OpCode, Action<Packet>> _packetHandlers;
public Connection() {
_packetHandlers = new Dictionary<OpCode, Action<Packet>>();
}
}
public sealed class Client : BaseConnection
{
public Client() : base() {
// Here will throw the errors...
// CS1503 Argument 2: cannot convert from 'method group' to 'Action<Packet>'
_packetHandlers.Add(OpCode.FirstPacket, OnReceiveFirst);
_packetHandlers.Add(OpCode.AnotherPacket, OnReceiveAnother);
}
public void OnReceiveFirst(FirstPacket packet) {
}
public void OnReceiveAnother(AnotherPacket packet) {
}
}
根据this回答,派生类是其基类的一个实例,不涉及任何转换。
在我的代码中,如果FirstPacket
和AnotherPacket
都 Packet
,为什么我必须使用lambda“强制转换”?
public sealed class Client : BaseConnection
{
public Client() : base() {
// This works...
_packetHandlers.Add(OpCode.FirstPacket, p => { OnReceiveFirst((FirstPacket)p); });
_packetHandlers.Add(OpCode.AnotherPacket, p => { OnReceiveAnother((AnotherPacket)p); });
}
public void OnReceiveFirst(FirstPacket packet) {
}
public void OnReceiveAnother(AnotherPacket packet) {
}
}
对我来说没有意义。
答案 0 :(得分:2)
首先,请注意你的lambdas
OnReceiveFirst
如果没有演员表,就无法编译。
您可以进行演员表的原因是您对系统的逻辑有足够的了解,以决定永远不会使用SecondPacket
参数调用OnReceiveFirst
。因此,您得出结论,演员阵容是安全的。
编译器无法得出相同的结论,因此它要求您手动提供强制转换。
方法组为不需要强制转换的情况提供快捷方式。例如,如果您像这样重写public void OnReceiveFirst(Packet packetOrig) {
FirstPacket packet = (FirstPacket)packetOrig;
...
}
_packetHandlers.Add(OpCode.FirstPacket, OnReceiveFirst); // Compiles
您可以将它与方法组语法一起使用:
raw_input
在这里,铸造仍然是你的责任,因为如果转换抛出异常,你将能够将错误跟踪到你自己的代码,而不是某些编译器魔法。