1

私は次のように列挙型のリストを持っています:

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

各列挙型の16進値は、次のように解読されます。

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

enum後で'を追加してもenum、すべての値を再割り当てすることにはならないように、'に値を割り当てるための最良の方法は何ですか。サブシステムIDと通知タイプのみが選択されているため、通知IDが自動的に割り当てられます。

たとえば、何千ものがありenum、手作業で番号を付けるかenum、途中に番号を追加する場合は番号を付け直す必要があると、煩わしいかもしれません。

ありがとう。

4

4 に答える 4

3

あなたが私に尋ねた場合、列挙値でこのデータをエンコードするべきではありません。この情報を取得できる場所ではなく、属性を適用することをお勧めします。列挙型の実際の値が を表し、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
于 2011-09-20T21:32:38.943 に答える
0

列挙型は 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,
}
于 2011-09-20T21:10:31.117 に答える
0

ジェフの答えに満足している場合、これは私見よりもはるかにクリーンなデザインです

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おそらく気に入らない依存関係を作成します。

于 2011-09-20T22:21:03.927 に答える
0

あなたの列挙型の目的は、特定のコードでイベントに名前を付けることだと思います。問題は、名前とコードの間の関連付けの正規のソースは何かということです。それがあなた(またはあなたのコード)である場合、番号を付け直す理由はありません。外部ソース (ドキュメントなど) からのものである場合は、コード生成 ( T4 テンプレートなど) を展開してみてください。

于 2011-09-20T21:52:00.037 に答える