C# 中的可切换唯一标识符

发布于 2024-08-03 04:05:56 字数 801 浏览 4 评论 0原文

我正在实现一个系统,用于在我正在编写的程序的不同部分之间发送消息。有一些通用消息类型以及一些特定于程序每个部分的消息类型。我想避免从每种类型的基本消息类派生所固有的层次结构腐烂,因此我将此类型封装在 int 或 ushort 中。然后,我使用“Messages”命名空间和带有一堆常量的静态类来集中不同的类型。然而,我遇到了必须为每个不同部分维护一个唯一数字列表的问题:

namespace Messages
{
    public static class Generic
    {
        public const Int32 Unknown = 0;
        public const Int32 Initialize = 1;
        ...
        public const Int32 Destroy = 10;
    }
}

然后在其他地方

namespace Messages
{
    public static class Graphics
    {
        public const Int32 Unknown = 0;
        public const Int32 AddGraphic = 11; // <-- ?
    }
}

拥有任意 11 似乎很困难,特别是如果我有其中几个,维护和更新以确保没有冲突似乎是一种痛苦。是否有一个简单的解决方案来确保每个对此的引用都是唯一的?我尝试使用静态只读,从静态构造函数中的 Unique.ID() 函数初始化它们,但如果我这样做,我无法对传递的消息类型进行 switch() ,因为它说“需要常量类型”对于每种情况。

I'm implementing a system to send Messages between different parts of a program I'm writing. There are some generic message types as well as some specific to each part of the program. I would like to avoid the hierarchy rot inherent in deriving from a base message class for each type, So i'm encapsulating this type in an int or ushort. Then, I centralize the different types with a "Messages" namespace, and a static class with a bunch of constants. However, I ran into the issue of having to maintain a list of unique numbers for each different section:

namespace Messages
{
    public static class Generic
    {
        public const Int32 Unknown = 0;
        public const Int32 Initialize = 1;
        ...
        public const Int32 Destroy = 10;
    }
}

Then elsewhere

namespace Messages
{
    public static class Graphics
    {
        public const Int32 Unknown = 0;
        public const Int32 AddGraphic = 11; // <-- ?
    }
}

Having that arbitrary 11 seems difficult, especially if I have several of these, maintaining and updating to make sure there are no collisions seems to be a pain. Is there an easy solution in order to make sure each reference to this is unique? I tried using static readonly, initializing them off of a Unique.ID() function in a static constructor, but if I do that I am unable to switch() over the passed Message type, as it says "A constant type is expected" for each case.

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

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

发布评论

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

评论(6

泡沫很甜 2024-08-10 04:05:56

您不使用枚举有什么原因吗?

public enum MessageTypes
{
    Unknown,
    Initialize,
    ...
}

- 编辑:

详细阐述我的评论,考虑

enum MessageType
{
    Update,
    Delete,
    Destroy
}

MessageType t = ...;

switch(t){
   case MessageType.Update:
       DoUpdate();
   }
}

与:

interface IActionable
{
   void Do ();
}


public abstract class ActionableBase : IActionable
{
   // some other things

   public abstract void Do ();
}


public class UpdateAction : ActionableBase
{
   public override void Do ()
   {
       // Update Code
   }
}

...

IActionable a = ...;
a.Do();

Is there some reason you aren't using enums?

public enum MessageTypes
{
    Unknown,
    Initialize,
    ...
}

-- Edit:

Elaborating on my comment, Consider

enum MessageType
{
    Update,
    Delete,
    Destroy
}

MessageType t = ...;

switch(t){
   case MessageType.Update:
       DoUpdate();
   }
}

Versus:

interface IActionable
{
   void Do ();
}


public abstract class ActionableBase : IActionable
{
   // some other things

   public abstract void Do ();
}


public class UpdateAction : ActionableBase
{
   public override void Do ()
   {
       // Update Code
   }
}

...

IActionable a = ...;
a.Do();
旧城烟雨 2024-08-10 04:05:56

您可以为每个类别使用一个数字范围。为该类定义一个基数,并向该基数添加 0、1、2 等。

You can use a number range for each class. Define a base number for the class and add 0, 1, 2, etc to that base number.

你的心境我的脸 2024-08-10 04:05:56

如果您想让它们保持数字,一种方法是将它们分为不同的大小:

namespace Messages
{
    public static class Generic
    { 
        // these messages are 3-figure numbers
        public const Int32 Unknown = 0;
        public const Int32 Initialize = 101;
        ...
        public const Int32 Destroy = 110;
    }

    public static class Graphics
    {
        // these messages are 4-figure numbers
        public const Int32 Unknown = 0;
        public const Int32 AddGraphic = 1001; // <-- ?
        // and so on...
    }

}

然后您只需确保保持在每种类型的消息的边界内即可。

If you want to keep them numeric one way is to divide them into different magnitudes:

namespace Messages
{
    public static class Generic
    { 
        // these messages are 3-figure numbers
        public const Int32 Unknown = 0;
        public const Int32 Initialize = 101;
        ...
        public const Int32 Destroy = 110;
    }

    public static class Graphics
    {
        // these messages are 4-figure numbers
        public const Int32 Unknown = 0;
        public const Int32 AddGraphic = 1001; // <-- ?
        // and so on...
    }

}

Then you just need to make sure that you keep within the boundaries for each type of message.

秋意浓 2024-08-10 04:05:56

这不是自动的,但它可能比在各处复制值更容易维护:

    public enum Generic
    {
        Unknown = 0,
        Initialize = 1,
        Destroy = 10
    }

    public enum Graphics
    {
        AddGraphic = Generic.Destroy + 1
    }

因此,您可以让所有特定枚举以先前枚举集中的值开始,并像这样构建它们。

在您的实际对象中,您可以将它们存储为 int,然后将任何枚举值转换为适当的 int。

尽管如此,在这种情况下继承似乎是不可避免的,因为数据模型中存在自然的层次结构。

This isn't automatic, but it may be a bit easier to maintain then copying the values everywhere:

    public enum Generic
    {
        Unknown = 0,
        Initialize = 1,
        Destroy = 10
    }

    public enum Graphics
    {
        AddGraphic = Generic.Destroy + 1
    }

So, you can have all of your specific enums start with the value from a previous enum set and build them up like that.

In your actual objects, you could store them as int's and just convert whatever enum value to the appropriate int.

Although, it seems that inheritance may be inevitable in this case since there is a natural hierarchy in your data model.

看海 2024-08-10 04:05:56

我建议您查找“命令”和“命令”之间的区别。 'message',这可能会帮助您得出这样的结论:在消息中使用幻数\枚举是一个坏主意。

理想情况下,您希望创建由听众观察并采取行动的“命令”......

HTH

Ollie

I suggest you lookup the difference between 'command' & 'message', this might help you come to the conclusion that the use of magic numbers\enums inside messages is a bad idea.

Ideally you want to create 'commands' that are observed and actioned by listeners...

HTH

Ollie

柠檬色的秋千 2024-08-10 04:05:56

如果您真的非常想这样做,您可以创建一个通用私有枚举来保存所有可能的值。

然后,您可以通过单独的类将这些值公开为只读属性,将枚举公开为 Int32 - 例如,

namespace Messages
{
    private enum AllMessageTypes
    {
        Update,
        Delete,
        Destroy,
        AddGraphic 
    }

    public static class Generic
    {
        public Int32 Update 
        {
            get { return (Int32)AllMessageTypes.Update; }
        }
        ...
    }

    public static class Graphics
    {
        public Int32 AddGraphic 
        {
            get { return (Int32)AllMessageTypes.AddGraphic ; }
        }
    }
}

但是 - 我建议您重新设计您的解决方案。这似乎是在自找麻烦(我相信人们会评论)

If you really, really want to do this, you can create one generic private Enum that holds all of the possible values.

You can then expose those values through your separate classes as read-only properties that expose the enums as Int32s - e.g.

namespace Messages
{
    private enum AllMessageTypes
    {
        Update,
        Delete,
        Destroy,
        AddGraphic 
    }

    public static class Generic
    {
        public Int32 Update 
        {
            get { return (Int32)AllMessageTypes.Update; }
        }
        ...
    }

    public static class Graphics
    {
        public Int32 AddGraphic 
        {
            get { return (Int32)AllMessageTypes.AddGraphic ; }
        }
    }
}

However - I'd recommend you redesign your solution. This seems to be asking for trouble (as I'm sure people will comment on)

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