先贴出代码再问我为什么会收到这个错误会更容易。
抽象类-数据包
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
}
抽象类-BaseConnection
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) {
}
}
这对我来说没有意义。
最佳答案
首先,请注意您的 lambda 表达式
p => { OnReceiveFirst((FirstPacket)p); }
如果没有转换将无法编译。
之所以可以进行转换,是因为您对系统的逻辑了解得足够多,可以决定永远不会使用 SecondPacket
的参数调用 OnReceiveFirst
。因此,您得出结论,类型转换是安全的。
另一方面,编译器无法得出相同的结论,因此它会要求您手动提供转换。
方法组为不需要转换的情况提供了一种捷径。例如,如果您像这样重写 OnReceiveFirst
public void OnReceiveFirst(Packet packetOrig) {
FirstPacket packet = (FirstPacket)packetOrig;
...
}
您可以将它与方法组语法一起使用:
_packetHandlers.Add(OpCode.FirstPacket, OnReceiveFirst); // Compiles
在这里,转换仍然是您的责任,因为如果转换抛出异常,您将能够将错误追溯到您自己的代码,而不是某些编译器魔法。
关于c# - 无法从 'method group' 转换为 Action,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47521961/