C# Can';t在抽象类型中定义静态方法。如何在周围工作?

C# Can';t在抽象类型中定义静态方法。如何在周围工作?,c#,C#,我目前正在为二进制应用程序协议开发一个库。 以下代码示例未编译(抽象类型中不允许静态方法定义。太糟糕了:()),但显示了我的意图: public abstract class CmdBody<T> { public static abstract byte[] ToBytes(T cmdBody); public abstract int GetLength(); } public class CmdBodyA : CmdBody<CmdBodyA> {

我目前正在为二进制应用程序协议开发一个库。 以下代码示例未编译(抽象类型中不允许静态方法定义。太糟糕了:()),但显示了我的意图:

public abstract class CmdBody<T>
{
    public static abstract byte[] ToBytes(T cmdBody);
    public abstract int GetLength();
}

public class CmdBodyA : CmdBody<CmdBodyA>
{
    static override byte[] ToBytes(CmdBodyA cmdBody) 
    { // Implementation }
}

public class CmdBodyB : CmdBody<CmdBodyB>
{
    static override byte[] ToBytes(CmdBodyB cmdBody)
    { // Implementation }
}

[...]

public class Cmd<T>
{ 
    public CmdHeader Header { get; set; }
    public CmdBody<T> Body { get; set; }

    public byte[] ToBytes()
    {
        byte[] cmdBytes = new byte[Header.GetLength() + Body.GetLength()];
        Header.ToBytes().CopyTo(cmdBytes, 0);
        Body.ToBytes().CoptyTo(cmdBytes, Header.GetLength());

        return cmdBytes;
    } 
}
公共抽象类CmdBody
{
公共静态抽象字节[]ToBytes(T cmdBody);
公共抽象int GetLength();
}
公共类CmdBody A:CmdBody
{
静态覆盖字节[]到字节(CmdBodyA cmdBody)
{//实现}
}
公共类CmdBody B:CmdBody
{
静态覆盖字节[]到字节(CmdBodyB cmdBody)
{//实现}
}
[...]
公共类Cmd
{ 
公共CmdHeader头{get;set;}
公共CmdBody主体{get;set;}
公共字节[]ToBytes()
{
byte[]cmdBytes=新字节[Header.GetLength()+Body.GetLength()];
Header.ToBytes().CopyTo(cmdBytes,0);
Body.ToBytes().CoptyTo(cmdBytes,Header.GetLength());
返回cmdBytes;
} 
}
非常基本的东西,Cmd由一个头和一个体组成,头类型是所有Cmd的通用类型,体具有不同的参数(属性),这取决于Cmd类型,我希望使用Cmd对象,并且能够对它们调用ToBytes(),通过网络发送它们

在我的实际实现中,我使用的是转换运算符而不是ToBytes()方法,但我希望代码示例保持简单,最后它完成相同的工作

我有很多不同的命令类型,我无法找到一个简单的解决方案,用一个通用的Cmd类型就可以实现我想要的。 我能想到的唯一解决方案是去掉基本CmdBody类中的静态方法,去掉泛型方面,并为每个CmdBody类型创建一个关联的Cmd类(类CmdA,类CmdB…),但这将在一天结束时导致大量代码重复

有什么好主意可以帮我解决这个问题吗?

你不能有“虚拟”静态方法,因为virtual/abstract/override建议在运行时重写实例

但是,您可以这样做:

public abstract class CmdBody
{
    public static byte[] ToBytes<T>(T cmdBody) where T : CmdBody
    {
         return cmdBody.ToBytes();
    }

    protected abstract byte[] ToBytes();

    public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
    protected override byte[] ToBytes() 
    { // Implementation }
}

public class CmdBodyB : CmdBody
{
    protected override byte[] ToBytes() 
    { // Implementation }
}
公共抽象类CmdBody
{
公共静态字节[]ToBytes(T cmdBody),其中T:cmdBody
{
返回cmdBody.ToBytes();
}
受保护的抽象字节[]ToBytes();
公共抽象int GetLength();
}
公共类CmdBody A:CmdBody
{
受保护的覆盖字节[]ToBytes()
{//实现}
}
公共类CmdBody B:CmdBody
{
受保护的覆盖字节[]ToBytes()
{//实现}
}
这允许每个“CmdBody”类型定义其自身的序列化方式,但基类静态方法是访问它的唯一公开方式

也就是说,考虑到您的用例,根本没有理由进行这种静态设置。您只需执行以下操作:

public abstract class CmdBody
{
    public abstract byte[] ToBytes();

    public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
    public override byte[] ToBytes() 
    { // Implementation }
}

public class CmdBodyB : CmdBody
{
    public override byte[] ToBytes() 
    { // Implementation }
}


public class Cmd<T> where T : CmdBody
{ 
    public CmdHeader Header { get; set; }
    public T Body { get; set; }

    public byte[] ToBytes()
    {
        byte[] cmdBytes = new byte[Header.GetLength() + Body.GetLength()];
        Header.ToBytes().CopyTo(cmdBytes, 0);
        Body.ToBytes().CopyTo(cmdBytes, Header.GetLength());

        return cmdBytes;
    } 
}
公共抽象类CmdBody
{
公共抽象字节[]ToBytes();
公共抽象int GetLength();
}
公共类CmdBody A:CmdBody
{
公共重写字节[]ToBytes()
{//实现}
}
公共类CmdBody B:CmdBody
{
公共重写字节[]ToBytes()
{//实现}
}
公共类Cmd,其中T:CmdBody
{ 
公共CmdHeader头{get;set;}
公共T体{get;set;}
公共字节[]ToBytes()
{
byte[]cmdBytes=新字节[Header.GetLength()+Body.GetLength()];
Header.ToBytes().CopyTo(cmdBytes,0);
Body.ToBytes().CopyTo(cmdBytes,Header.GetLength());
返回cmdBytes;
} 
}

您是否可能在寻找接口而不是抽象类型?抽象类型用于定义从其继承的类,其中接口用于定义要实现的类所需的方法和字段。这无关紧要。接口或抽象类不能定义静态方法,设计问题可能会解决ain.=/如果不在抽象类上实现,就不能定义静态方法。(静态成员不能标记为覆盖、虚拟或抽象)@Pheonixblade9他确实想要一个契约(接口),但是说“要派生,还必须提供一个静态方法ToBytes”。这很有意义,你不能定义静态存根-静态方法(或变量)每个类都是单数的,即其可继承但不可重写。您应该在抽象类中定义实现。从外观上看,您使用的是泛型,它应该允许您传入任何类型,并且您可以使用泛型约束来定义T应该是什么类型。哇!在您的第一个代码samp中做得非常好le.Sexy stuff:)非常感谢您的第二个建议(您只需编辑它以删除CmdBody中的一个ToBytes()定义)。非常感谢!@darkey修复了ToBytes的问题。。。