C# C语言中的可切换唯一标识符#
我正在实现一个系统,在我编写的程序的不同部分之间发送消息。有一些通用消息类型,也有一些特定于程序每个部分的消息类型。我希望避免从每个类型的基本消息类派生时固有的层次结构腐烂,因此我将此类型封装在int或ushort中。然后,我用一个“Messages”名称空间和一个带有一组常量的静态类来集中不同的类型。但是,我遇到了一个问题,即必须为每个不同的部分维护一个唯一编号的列表:C# C语言中的可切换唯一标识符#,c#,constants,uniqueidentifier,switch-statement,C#,Constants,Uniqueidentifier,Switch Statement,我正在实现一个系统,在我编写的程序的不同部分之间发送消息。有一些通用消息类型,也有一些特定于程序每个部分的消息类型。我希望避免从每个类型的基本消息类派生时固有的层次结构腐烂,因此我将此类型封装在int或ushort中。然后,我用一个“Messages”名称空间和一个带有一组常量的静态类来集中不同的类型。但是,我遇到了一个问题,即必须为每个不同的部分维护一个唯一编号的列表: namespace Messages { public static class Generic {
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; // <-- ?
}
}
命名空间消息
{
公共静态类图形
{
public const Int32未知=0;
public const Int32 AddGraphic=11;//不使用枚举有什么原因吗
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();
您不使用枚举有什么原因吗
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();
您可以为每个类使用一个数字范围。为该类定义一个基数,并将0、1、2等添加到该基数中。您可以为每个类使用一个数字范围。为该类定义一个基数,并将0、1、2等添加到该基数中。如果要使它们保持数字化,一种方法是将它们划分为不同的大小:
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...
}
}
命名空间消息
{
公共静态类泛型
{
//这些信息是三位数
public const Int32未知=0;
public const Int32 Initialize=101;
...
公共常数Int32=110;
}
公共静态类图形
{
//这些信息是4位数的数字
public const Int32未知=0;
public const Int32 AddGraphic=1001;//如果要将它们保持为数字,一种方法是将它们划分为不同的大小:
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...
}
}
命名空间消息
{
公共静态类泛型
{
//这些信息是三位数
public const Int32未知=0;
public const Int32 Initialize=101;
...
公共常数Int32=110;
}
公共静态类图形
{
//这些信息是4位数的数字
public const Int32未知=0;
public const Int32 AddGraphic=1001;//这不是自动的,但可能比在任何地方复制值更容易维护:
public enum Generic
{
Unknown = 0,
Initialize = 1,
Destroy = 10
}
public enum Graphics
{
AddGraphic = Generic.Destroy + 1
}
因此,您可以让所有特定的枚举从上一个枚举集中的值开始,然后像这样构建它们
在实际对象中,可以将它们存储为int,并将任何枚举值转换为适当的int
尽管如此,在这种情况下继承似乎是不可避免的,因为您的数据模型中有一个自然的层次结构。这不是自动的,但它可能比在任何地方复制值更容易维护:
public enum Generic
{
Unknown = 0,
Initialize = 1,
Destroy = 10
}
public enum Graphics
{
AddGraphic = Generic.Destroy + 1
}
因此,您可以让所有特定的枚举从上一个枚举集中的值开始,然后像这样构建它们
在实际对象中,可以将它们存储为int,并将任何枚举值转换为适当的int
尽管如此,在这种情况下继承似乎是不可避免的,因为数据模型中有一个自然的层次结构。我建议您查找“命令”和“消息”之间的区别,这可能会帮助您得出结论,在消息中使用幻数\enum是一个坏主意
理想情况下,您希望创建由侦听器观察和执行的“命令”
嗯
Ollie我建议您查找“命令”和“消息”之间的区别,这可能会帮助您得出结论,在消息中使用幻数\enum是一个坏主意
理想情况下,您希望创建由侦听器观察和执行的“命令”
嗯
Ollie如果您真的非常想这样做,您可以创建一个通用私有枚举来保存所有可能的值
然后,您可以通过单独的类将这些值作为只读属性公开,这些只读属性将枚举公开为Int32s—例如
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 ; }
}
}
}
但是-我建议您重新设计解决方案。这似乎会带来麻烦(我相信人们会对此发表评论)如果您真的非常想这样做,您可以创建一个包含所有可能值的通用私有枚举
然后,您可以通过单独的类将这些值作为只读属性公开,这些只读属性将枚举公开为Int32s—例如
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 ; }
}
}
}
但是-我建议您重新设计您的解决方案。这似乎会带来麻烦(我相信人们会对此发表评论)枚举不允许我“切分”不同消息类型的声明。switch(message.Type){case Messages.Generic.Initialize:break;case Messages.Graphics.AddGraphic:break;}(呃,上面的格式很奇怪,但我相信你明白了。)总的来说,我真的认为你最好重新考虑一下你的设计。在C#中,你真的不应该有任何int
常量来识别消息。你通常应该使用enum
,或者某种形式的继承/操作系统。@Damian ints(或enums)对于无法管理的子类,OOPS从来都不是合适的解决方案。首先,OOPS的概念旨在减少switch和if类型的语句。您可以使用遗传学和良好的层次结构重新设计语句,而不是强制转换和switch语句。精心设计的虚拟方法和重写方法更快,也更易于维护num不允许我“切分”不同消息类型的声明。switch(message.Type){case Messages.Generic.Initialize:break;case Messages.Graphics.AddGraphic:break;}(呃,它的格式很奇怪,但我相信你明白了。)总的来说,我真的认为你最好重新考虑一下你的设计