如何在.NET类库中创建"抽象"枚举?

Laz*_*zlo 12 c# enums abstract

我正在创建一个服务器库,其中数据包关联由枚举完成.

public enum ServerOperationCode : byte
{
    LoginResponse = 0x00,
    SelectionResponse = 0x01,
    BlahBlahResponse = 0x02
}

public enum ClientOperationCode : byte
{
    LoginRequest = 0x00,
    SelectionRequest = 0x01,
    BlahBlahRequest = 0x02
}
Run Code Online (Sandbox Code Playgroud)

当你在自己的项目中工作时,这很好 - 你可以比较返回哪个枚举成员(即if (packet.OperationCode == ClientOperationCode.LoginRequest)).但是,由于这是一个类库,用户必须定义​​自己的枚举.

因此,我有两个枚举添加为"抽象" - ServerOperationCode和ClientOperationCode.我知道在C#中实现抽象枚举是不可能的.我该怎么做呢?

Der*_*ley 14

当我需要这样做时,我喜欢在我的类上使用静态实例.它允许您拥有一些默认值,但也可以通过常规的继承和接口实现方式进行扩展:

    public abstract class OperationCode
    {
        public byte Code { get; private set; }
        public OperationCode(byte code)
        {
            Code = code;
        }
    }

    public class ServerOperationCode : OperationCode
    {
        public static ServerOperationCode LoginResponse = new ServerOperationCode(0x00);
        public static ServerOperationCode SelectionResponse = new ServerOperationCode(0x01);
        public static ServerOperationCode BlahBlahResponse = new ServerOperationCode(0x02);

        public ServerOperationCode(byte code) : base(code) { }
    }

    public class ClientOperationCode : OperationCode
    {
        public static ClientOperationCode LoginRequest = new ClientOperationCode(0x00);
        public static ClientOperationCode SelectionRequest = new ClientOperationCode(0x01);
        public static ClientOperationCode BlahBlahRequest = new ClientOperationCode(0x02);

        public ClientOperationCode(byte code) : base(code) { }
    }
Run Code Online (Sandbox Code Playgroud)

假设packet.OperationCode返回一个字节,您可能必须为字节实现==运算符.将此代码放入您的抽象OperationCode类中.

public static bool operator ==(OperationCode a, OperationCode b)
{
  return a.Code == b.Code;
}

public static bool operator !=(OperationCode a, OperationCode b)
{
  return !(a == b);
}
Run Code Online (Sandbox Code Playgroud)

这将允许您进行与您显示的相同的检查:

if (packet.OperationCode == ClientOperationCode.LoginRequest)
Run Code Online (Sandbox Code Playgroud)


小智 7

为什么每个人都认为枚举不能抽象?

类System.Enum IS枚举的抽象。

您可以将任何枚举值分配给Enum,也可以将其强制转换回原始枚举,也可以使用名称或值。

例如:

这小段代码来自我的控件库之一中使用的动态属性集合。我允许通过枚举值创建和访问属性,以使其速度更快,并减少人为错误

    /// <summary>
    /// creates a new trigger property.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    protected virtual TriggerProperty<T> Create<T>(T value, Enum name)
    {
        var pt = new TriggerProperty<T>(value, OnPropertyChanged, Enum.GetName(name.GetType(), name));
        _properties[name.GetHashCode()] = pt;
        return pt;
    }
Run Code Online (Sandbox Code Playgroud)

我用于Enum.GetName(Type, object)获取枚举值的名称(为属性提供名称),出于速度和一致性的原因,我用于GetHashCode()返回枚举成员的整数值(int的哈希码始终只是int值)

这是该方法被调用的示例:

    public enum Props
    {
        A, B, C, Color, Type, Region, Centre, Angle
    }

    public SpecularProperties()
        :base("SpecularProperties", null)
    {
        Create<double>(1, Props.A);
        Create<double>(1, Props.B);
        Create<double>(1, Props.C);
        Create<Color>(Color.Gray, Props.Color);
        Create<GradientType>(GradientType.Linear, Props.Type);
        Create<RectangleF>(RectangleF.Empty, Props.Region);
        Create<PointF>(PointF.Empty, Props.Centre);
        Create<float>(0f, Props.Angle);
    }
Run Code Online (Sandbox Code Playgroud)