C # alternative to enums for n: m relationship

There are several threads in ranges of values ​​in enumerations (this is not possible). But I have the following problem and the search for a better solution, where none of the ones provided to me satisfied me.

The protocol specification says that byte [x] of the message, the type of message, has the following possible values ​​(fantasy values):

0x00 = get 0x01 = set 0x02 to 0xFF = identify 

Thus, there are only 3 different logical options that will best be considered in the listing. But one of the n logical options has m different numerical copies with which it is impossible to translate into an enumeration.

Now what is the best (cleanest) solution for such a problem? I could create a 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; } } 

I could also create a class without enum, but with static members.

In any case, one problem arises. If someone tries to send a packet, he can use

 if (messageBytes[x] == (byte)MessageTypeEnum.identify) { // do stuff } 

But messageByte [x] can be anything between 0x02 and 0xFF, so "hit" the value specified in the enumeration would be pure luck. On the other hand, I want the enum (or static member) to be publicly available for easy posting.

Can I somehow use the use of my getLogicalValue () function - Function? Is there a more elegant solution?

All I want is a simple and well-structured way of associating logical values ​​with numerical values ​​with respect to n: m. Moreover, this protocol has many such cases, and I would like to keep my code neat.

Thanks for your help and time :)

Janis

+6
source share
3 answers

I recommend that you abandon the idea of ​​using enumerations and create a custom type for it.

It can be either a structure or a class; it does not matter. You can solve the equality problem by overloading the == operator and providing your own implementation.

Something like that:

 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 } 

Remember to implement Equals and GetHashCode for consistency in implementing peers.

+4
source

In fact, I would use enumeration values ​​only as identifiers, and not as actual values. Something like that:

 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; } } 

And use it like this:

 if (MessageType.getLogicalValue(messageBytes[x]) == MessageTypeEnum.identify) { // do stuff } 

Of course, you can use switch instead of if... else if... , which depends on your personal preferences and needs.

As pointed out in another answer, if you want to use direct comparison, you need to create your own class and implement equality comparison with what you need.

+3
source

you could reorganize the method signature and do the following, and it will tell you which enum by name it really is, passing in value a look at the method that I just reworked for you, and how to call it below

 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(); } 

Call a static method like this

 var enumValue = getLogicalValue(0x02); 

the return string will identify or if you want to make a switch / case statement, you can also do the following

  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; } 
0
source

Source: https://habr.com/ru/post/981622/


All Articles