c# - 无法从 'method group' 转换为 Action

标签 c# subtype

先贴出代码再问我为什么会收到这个错误会更容易。

抽象类-数据包

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答案是,派生类是其基类的一个实例,不涉及转换。

在我的代码中,如果 FirstPacketAnotherPacket 都是 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/

相关文章:

c# - mapwingis 形状没有添加到 shapefile

c# - 表达式树 - 在外部 lambda 中编译内部 lambda - 作用域解析

c# - 如何将 "default(SomeType)"从 C# 转换为 CIL?

c# - 使用导致异常的表达式过滤 EfCore DbSet

子类型的 Swift 协议(protocol)一致性要求

Coq:绕过统一继承条件

types - Ada类型声明语义

c# - 基于 Microsoft Word 模板生成 PDF 文档

c++ - 变体,C++中的存在多态性

go - 我们可以为 Go 中的错误创建子类型吗?