可以很好地处理枚举和十六进制值

发布于 2024-12-06 01:30:38 字数 673 浏览 5 评论 0原文

我有一个枚举列表,如下所示:

public enum EventID : uint
{
    SAMPLE_EVENT_1 = 0xDCCA0000,
    SAMPLE_EVENT_2 = 0xDCCB0001,
    SAMPLE_EVENT_3 = 0xDCCA0002,
    SAMPLE_EVENT_4 = 0xDCC00003,
    SAMPLE_EVENT_5 = 0xDCCA0004,
    ...
}

每个枚举的十六进制值解密如下:

/// DCC X XXXX 
/// --- - ----
///  |  |  |--> Notification ID (0x0000 to 0xFFFF)
///  |  |-----> Notification Type (0x0 to 0xA)
///  |--------> Sub-system ID (0xDCC)

将值分配给enum的最佳方法是什么,例如添加enum 的后面并不意味着重新分配所有值。选择唯一的子系统 ID 和通知类型,通知 ID 应自动分配。

例如,如果有数千个枚举,并且我必须手动对它们进行编号,或者如果在中间添加枚举,则需要重新编号,这可能会很烦人。

谢谢。

I have a list of enums as follows:

public enum EventID : uint
{
    SAMPLE_EVENT_1 = 0xDCCA0000,
    SAMPLE_EVENT_2 = 0xDCCB0001,
    SAMPLE_EVENT_3 = 0xDCCA0002,
    SAMPLE_EVENT_4 = 0xDCC00003,
    SAMPLE_EVENT_5 = 0xDCCA0004,
    ...
}

The hex value for each enum is deciphered as follows:

/// DCC X XXXX 
/// --- - ----
///  |  |  |--> Notification ID (0x0000 to 0xFFFF)
///  |  |-----> Notification Type (0x0 to 0xA)
///  |--------> Sub-system ID (0xDCC)

What is the best way to assign values to the enum's, such that adding enum's later won't mean reassigning all the values. The only Sub-system ID, and Notification Type are chosen, the Notification ID should be automatically assigned.

For example, it might get annoying if there were thousands of enum's and I had to number them by hand or renumber them if adding an enum in the middle.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

在巴黎塔顶看东京樱花 2024-12-13 01:30:38

如果您问我,您不应该在枚举值中编码这些数据。最好将属性应用于它们,而不是在可以获得此信息的地方。让枚举的实际值代表 NotificationId 以获取自动分配的值。

[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]
public class SubsystemIdAttribute : Attribute
{
    public SubsystemIdAttribute(ushort value)
    {
        this.Value = (ushort)(value & 0xFFF);
    }

    public ushort Value { get; private set; }
}

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class NotificationTypeAttribute : Attribute
{
    public NotificationTypeAttribute(byte value)
    {
        this.Value = (byte)(value & 0xF);
    }

    public byte Value { get; private set; }
}

public enum EventId
{
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_1,
    [SubsystemId(0xDCC)] [NotificationType(0xB)] SAMPLE_EVENT_2,
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_3,
    [SubsystemId(0xDCC)] [NotificationType(0x0)] SAMPLE_EVENT_4,
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_5,
}

public static class EventIdExtensions
{
    public static ushort GetSubsystemId(this EventId eventId)
    {
        return GetAttributeValue(eventId, (SubsystemIdAttribute a) => a.Value);
    }

    public static byte GetNotificationType(this EventId eventId)
    {
        return GetAttributeValue(eventId, (NotificationTypeAttribute a) => a.Value);
    }

    private static TValue GetAttributeValue<TAttribute, TValue>(EventId eventId, Func<TAttribute, TValue> selector)
        where TAttribute : Attribute
    {
        return typeof(EventId).GetField(eventId.ToString())
            .GetCustomAttributes(false)
            .OfType<TAttribute>()
            .Select(selector)
            .Single();
    }
}

要获取属性的值,请调用适当的扩展方法。

var eventId = EventId.SAMPLE_EVENT_3;
var subsystemId = eventId.GetSubsystemId();           // 0xDCC
var notificationType = eventId.GetNotificationType(); // 0xA

If you asked me, you shouldn't be encoding this data in your enum values. It would be better to apply attributes the them instead where you could get this information. Let the actual value of the enum represent the NotificationId to get the automatically assigned values.

[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]
public class SubsystemIdAttribute : Attribute
{
    public SubsystemIdAttribute(ushort value)
    {
        this.Value = (ushort)(value & 0xFFF);
    }

    public ushort Value { get; private set; }
}

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class NotificationTypeAttribute : Attribute
{
    public NotificationTypeAttribute(byte value)
    {
        this.Value = (byte)(value & 0xF);
    }

    public byte Value { get; private set; }
}

public enum EventId
{
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_1,
    [SubsystemId(0xDCC)] [NotificationType(0xB)] SAMPLE_EVENT_2,
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_3,
    [SubsystemId(0xDCC)] [NotificationType(0x0)] SAMPLE_EVENT_4,
    [SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_5,
}

public static class EventIdExtensions
{
    public static ushort GetSubsystemId(this EventId eventId)
    {
        return GetAttributeValue(eventId, (SubsystemIdAttribute a) => a.Value);
    }

    public static byte GetNotificationType(this EventId eventId)
    {
        return GetAttributeValue(eventId, (NotificationTypeAttribute a) => a.Value);
    }

    private static TValue GetAttributeValue<TAttribute, TValue>(EventId eventId, Func<TAttribute, TValue> selector)
        where TAttribute : Attribute
    {
        return typeof(EventId).GetField(eventId.ToString())
            .GetCustomAttributes(false)
            .OfType<TAttribute>()
            .Select(selector)
            .Single();
    }
}

To get the values of the attributes, call the appropriate extension methods.

var eventId = EventId.SAMPLE_EVENT_3;
var subsystemId = eventId.GetSubsystemId();           // 0xDCC
var notificationType = eventId.GetNotificationType(); // 0xA
真心难拥有 2024-12-13 01:30:38

枚举仅自动递增 1,因此您必须按子系统、通知类型、通知 id 保持它们的顺序,只有当存在间隙时才分配。因此,为了保持正确的顺序,上面的枚举将如下所示:

public enum EventID : uint
{
    SAMPLE_EVENT_1 = 0xDCCA0000,
    SAMPLE_EVENT_3 = 0xDCCA0002,
    SAMPLE_EVENT_5 = 0xDCCA0004,
    SAMPLE_EVENT_2 = 0xDCCB0001,
    SAMPLE_EVENT_4 = 0xDCC00003,
}

Enums only auto-increment by 1, so you'd have to keep them in order by sub-system, then notification type, then notification id, and only when there are gaps would you assign. So to keep order proper, your above enum would look like this:

public enum EventID : uint
{
    SAMPLE_EVENT_1 = 0xDCCA0000,
    SAMPLE_EVENT_3 = 0xDCCA0002,
    SAMPLE_EVENT_5 = 0xDCCA0004,
    SAMPLE_EVENT_2 = 0xDCCB0001,
    SAMPLE_EVENT_4 = 0xDCC00003,
}
暗藏城府 2024-12-13 01:30:38

我想您枚举的目的是用特定代码为事件命名。问题是名称和代码之间关联的规范来源是什么。如果是您(或您的代码),我看不出有任何理由重新编号。如果它来自某些外部源(例如文档),请尝试部署一些代码生成(例如 T4 模板)。

I guess that purpose of your enums is to give a names to the events with specific codes. The question is what is the canonical source of association between names and codes. If it is you (or your code) I don't see any reason to renumber. If it comes from some external source (e.g. documentation) try to deploy some code generation (e.g. T4 templates).

秋叶绚丽 2024-12-13 01:30:38

如果您对 Jeff 的回答感到满意恕我直言,这是更简洁的设计

public class EventId
{
    public static readonly SAMPLE_EVENT_1 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_2 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_3 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_4 = new EventId(0xDCC, 0xA);

    public readonly ushort SubSystemId;
    public readonly byte NotificationType;
    public readonly ushort NotificationId;

    private static ushort notificationCounter = 0;

    private EventId(ushort subSystemId, byte notificationType)
    {
        this.SubSystemId = subSystemId;
        this.NotificationType= notificationType;
        this.NotificationId = notificationCounter++;
    }
}

,但是当然,您在编译器和 NotificationId 之间创建了依赖关系,您可能不喜欢这种依赖关系。

If you are happy with Jeff's answer this is imho much more cleaner design

public class EventId
{
    public static readonly SAMPLE_EVENT_1 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_2 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_3 = new EventId(0xDCC, 0xA);
    public static readonly SAMPLE_EVENT_4 = new EventId(0xDCC, 0xA);

    public readonly ushort SubSystemId;
    public readonly byte NotificationType;
    public readonly ushort NotificationId;

    private static ushort notificationCounter = 0;

    private EventId(ushort subSystemId, byte notificationType)
    {
        this.SubSystemId = subSystemId;
        this.NotificationType= notificationType;
        this.NotificationId = notificationCounter++;
    }
}

But of course you creating dependency between compiler and NotificationId which you probably don't like.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文