簡體   English   中英

無法從“方法組”轉換為“操作”

[英]Cannot convert from 'method group' to Action

首先發布代碼會更容易,然后問我為什么會收到此錯誤。

抽象類 - 數據包

abstract class Packet
{
    // base class!
}

我的第一個包

public sealed class FirstPacket : Packet
{
    // First packet implementations...
}

另一個包

public sealed class AnotherPacket : Packet
{
    // Another packet implementations...
}

數據包OpCodes

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) {
    }
}

根據這個答案,派生類是其基類的一個實例,不涉及任何轉換。

在我的代碼中,如果FirstPacketAnotherPacket 都是 Packet ,為什么我必須使用lambda“ AnotherPacket轉換”?

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) {
    }
}

這對我來說沒有意義。

首先,請注意你的lambdas

p => { OnReceiveFirst((FirstPacket)p); }

沒有演員陣容就不會編譯。

您可以進行OnReceiveFirst的原因是您對系統的邏輯有足夠的了解,以決定永遠不會使用SecondPacket參數調用OnReceiveFirst 因此,您得出結論,演員是安全的。

另一方面,編譯器無法得出相同的結論,因此它會要求您手動提供強制轉換。

方法組為不需要強制轉換的情況提供快捷方式。 例如,如果您像這樣重寫OnReceiveFirst

public void OnReceiveFirst(Packet packetOrig) {
    FirstPacket packet = (FirstPacket)packetOrig;
    ...
}

您可以將它與方法組語法一起使用:

_packetHandlers.Add(OpCode.FirstPacket, OnReceiveFirst); // Compiles

在這里,cast也是你的責任,因為如果轉換拋出異常,你將能夠將錯誤跟蹤到你自己的代碼,而不是某些編譯魔術。

因為onReceiveFirstOnReceiveAnother期望比Packet更具體的類型。 FirstPacketAnotherPacket都是數據包類型,但AnotherPacket不能替代FirstPacket ,反之亦然。

如果OnReceiveFirstOnReceiveAnother只需要訪問Packet類型聲明的內容而不是子類中的任何內容,則可以將定義更改為:

public void OnReceiveFirst(Packet packet) {}
public void OnReceiveAnother(Packet packet) {}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM