C# 替代 n:m 关系的枚举
C# alternative to enums for a n:m-relation
枚举中的值范围有多个线程(不可能)。
但是我有以下问题并搜索最佳解决方案,其中 none 所提供的曾经让我非常满意。
协议规范说明消息的字节[x],即消息类型,具有以下可能的值(幻想值):
0x00 = get
0x01 = set
0x02 to 0xFF = identify
所以只有 3 个不同的逻辑选项,最好在枚举中处理。但是n个逻辑选项中的一个有m个不同的数值对应物,这是不可能在枚举中处理的。
对于这样的问题,最好(最干净)的解决方案是什么?
我可以建一个 class
class MessageType {
public enum MessageTypeEnum {
get = 0x00,
set = 0x01,
identify = 0x02
}
public static MessageTypeEnum getLogicalValue (byte numericalValue)
{
if (numericalValue < 0x02)
return (MessageTypeEnum(numericalValue));
else
return MessageTypeEnum.identify;
}
}
我也可以创建一个没有枚举但有静态成员的 class。
无论哪种方式都有一个问题:如果有人试图发送数据包,他可能会使用
if (messageBytes[x] == (byte)MessageTypeEnum.identify) {
// do stuff
}
但是 messageByte[x] 可以是 0x02 和 0xFF 之间的任何值,因此 "hitting" 枚举中指定的值纯属运气。另一方面,我希望枚举(或静态成员)为 public 以便于构建消息。
我能否以某种方式强制使用我的 getLogicalValue() 函数?
有没有更优雅的解决方案?
我想要的只是一种简单且结构良好的方法,可以将 link 逻辑值转换为 n:m 关系中的数值。特别是因为给定的协议有很多这样的情况,我想保持我的代码整洁。
感谢您的帮助和时间:)
贾尼斯
实际上我只会将枚举值用作标识符而不是实际值。像这样:
class MessageType {
public enum MessageTypeEnum {
get,
set,
identify
}
public static MessageTypeEnum getLogicalValue (byte numericalValue)
{
if (numericalValue == 0x00)
return MessageTypeEnum.get;
else if (numericalValue == 0x01)
return MessageTypeEnum.set;
else
return MessageTypeEnum.identify;
}
}
并这样使用:
if (MessageType.getLogicalValue(messageBytes[x]) == MessageTypeEnum.identify) {
// do stuff
}
您当然可以使用switch
代替if... else if...
,这取决于您的个人喜好和需要。
如其他答案所述,如果您想使用直接比较,则需要创建自定义 class 并根据需要实施相等比较。
我建议您放弃使用枚举的想法并为此创建一个自定义类型。
可以是struct,也可以是class;没关系。您可以通过重载 ==
运算符并提供自定义实现来解决等于问题。
像这样:
public class MessageType
{
private readonly byte value;
private MessageType(byte value)
{
this.value = value;
}
public static readonly MessageType Get = new MessageType(0);
public static readonly MessageType Set = new MessageType(1);
public static readonly MessageType Identify = new MessageType(2);
public static bool operator ==(MessageType m, byte b)
{
if (object.ReferenceEquals(m, null))
return false;
if (m.value == 2 && b >= 2 && b <= 0xff)//I think <= check is redundant
return true;
return m.value == b;
}
public static bool operator !=(MessageType m, byte b)
{
return !(m == b);
}
//Need to implement Equals, GetHashCode etc
}
不要忘记实施 Equals
和 GetHashCode
以确保 equals 实施的一致性。
你可以重构方法签名并执行以下操作,它会通过传入值告诉你它实际上是哪个 enum
看看我刚刚为你重构的方法以及如何调用它以下
public static string getLogicalValue(byte numericalValue)
{
Type type = numericalValue.GetType();
var name = Enum.GetName(typeof(MessageTypeEnum), numericalValue);
if (numericalValue < 0x02)
return name;
else
return MessageTypeEnum.identify.ToString();
}
像这样调用静态方法
var enumValue = getLogicalValue(0x02);
return 字符串将是 identify
或者,如果您想执行 switch/case 语句,您也可以执行以下操作
public static string getLogicalValue(byte numericalValue)
{
Type type = numericalValue.GetType();
var name = Enum.GetName(typeof(MessageTypeEnum), numericalValue);
switch(numericalValue)
{
case 0x00:
{
name= (MessageTypeEnum.get.ToString());
break;
}
case 0x01:
{
name= (MessageTypeEnum.set.ToString());
break;
}
default:
{
name= (MessageTypeEnum.identify.ToString());
break;
}
}
return name;
}
枚举中的值范围有多个线程(不可能)。 但是我有以下问题并搜索最佳解决方案,其中 none 所提供的曾经让我非常满意。
协议规范说明消息的字节[x],即消息类型,具有以下可能的值(幻想值):
0x00 = get
0x01 = set
0x02 to 0xFF = identify
所以只有 3 个不同的逻辑选项,最好在枚举中处理。但是n个逻辑选项中的一个有m个不同的数值对应物,这是不可能在枚举中处理的。
对于这样的问题,最好(最干净)的解决方案是什么? 我可以建一个 class
class MessageType {
public enum MessageTypeEnum {
get = 0x00,
set = 0x01,
identify = 0x02
}
public static MessageTypeEnum getLogicalValue (byte numericalValue)
{
if (numericalValue < 0x02)
return (MessageTypeEnum(numericalValue));
else
return MessageTypeEnum.identify;
}
}
我也可以创建一个没有枚举但有静态成员的 class。
无论哪种方式都有一个问题:如果有人试图发送数据包,他可能会使用
if (messageBytes[x] == (byte)MessageTypeEnum.identify) {
// do stuff
}
但是 messageByte[x] 可以是 0x02 和 0xFF 之间的任何值,因此 "hitting" 枚举中指定的值纯属运气。另一方面,我希望枚举(或静态成员)为 public 以便于构建消息。
我能否以某种方式强制使用我的 getLogicalValue() 函数? 有没有更优雅的解决方案?
我想要的只是一种简单且结构良好的方法,可以将 link 逻辑值转换为 n:m 关系中的数值。特别是因为给定的协议有很多这样的情况,我想保持我的代码整洁。
感谢您的帮助和时间:)
贾尼斯
实际上我只会将枚举值用作标识符而不是实际值。像这样:
class MessageType {
public enum MessageTypeEnum {
get,
set,
identify
}
public static MessageTypeEnum getLogicalValue (byte numericalValue)
{
if (numericalValue == 0x00)
return MessageTypeEnum.get;
else if (numericalValue == 0x01)
return MessageTypeEnum.set;
else
return MessageTypeEnum.identify;
}
}
并这样使用:
if (MessageType.getLogicalValue(messageBytes[x]) == MessageTypeEnum.identify) {
// do stuff
}
您当然可以使用switch
代替if... else if...
,这取决于您的个人喜好和需要。
如其他答案所述,如果您想使用直接比较,则需要创建自定义 class 并根据需要实施相等比较。
我建议您放弃使用枚举的想法并为此创建一个自定义类型。
可以是struct,也可以是class;没关系。您可以通过重载 ==
运算符并提供自定义实现来解决等于问题。
像这样:
public class MessageType
{
private readonly byte value;
private MessageType(byte value)
{
this.value = value;
}
public static readonly MessageType Get = new MessageType(0);
public static readonly MessageType Set = new MessageType(1);
public static readonly MessageType Identify = new MessageType(2);
public static bool operator ==(MessageType m, byte b)
{
if (object.ReferenceEquals(m, null))
return false;
if (m.value == 2 && b >= 2 && b <= 0xff)//I think <= check is redundant
return true;
return m.value == b;
}
public static bool operator !=(MessageType m, byte b)
{
return !(m == b);
}
//Need to implement Equals, GetHashCode etc
}
不要忘记实施 Equals
和 GetHashCode
以确保 equals 实施的一致性。
你可以重构方法签名并执行以下操作,它会通过传入值告诉你它实际上是哪个 enum
看看我刚刚为你重构的方法以及如何调用它以下
public static string getLogicalValue(byte numericalValue)
{
Type type = numericalValue.GetType();
var name = Enum.GetName(typeof(MessageTypeEnum), numericalValue);
if (numericalValue < 0x02)
return name;
else
return MessageTypeEnum.identify.ToString();
}
像这样调用静态方法
var enumValue = getLogicalValue(0x02);
return 字符串将是 identify
或者,如果您想执行 switch/case 语句,您也可以执行以下操作
public static string getLogicalValue(byte numericalValue)
{
Type type = numericalValue.GetType();
var name = Enum.GetName(typeof(MessageTypeEnum), numericalValue);
switch(numericalValue)
{
case 0x00:
{
name= (MessageTypeEnum.get.ToString());
break;
}
case 0x01:
{
name= (MessageTypeEnum.set.ToString());
break;
}
default:
{
name= (MessageTypeEnum.identify.ToString());
break;
}
}
return name;
}