[英]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...
}
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) {
}
}
根據這個答案,派生類是其基類的一個實例,不涉及任何轉換。
在我的代碼中,如果FirstPacket
和AnotherPacket
都是 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也是你的責任,因為如果轉換拋出異常,你將能夠將錯誤跟蹤到你自己的代碼,而不是某些編譯魔術。
因為onReceiveFirst
和OnReceiveAnother
期望比Packet
更具體的類型。 FirstPacket
和AnotherPacket
都是數據包類型,但AnotherPacket
不能替代FirstPacket
,反之亦然。
如果OnReceiveFirst
和OnReceiveAnother
只需要訪問Packet
類型聲明的內容而不是子類中的任何內容,則可以將定義更改為:
public void OnReceiveFirst(Packet packet) {}
public void OnReceiveAnother(Packet packet) {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.