Atrotygma
Atrotygma

Reputation: 1153

Constants vs enum regarding to parsing

I'm currently writing a simple parser for streaming information delivered using the Session Description Protocol (SDP; see: https://www.rfc-editor.org/rfc/rfc4566).

For various fields, such as originator or media, there are flags which can have different values. For example, the media transport protocol on media field (see: https://www.rfc-editor.org/rfc/rfc4566#section-8.2.2)

m=audio 49170 RTP/AVP 0

The proto flag (media transport protocol) can either be "RTP/AVP", "RTP/SAVP" or "UDP" according to the specification.

Because there are numerous values this flag can have, it's appropriate to use an enum:

public enum MediaTransportProtocol {
    UDP,
    RTP_AVP
    RTP_SAVP
}

But now here's the problem: There's no such thing as a string enum, so I can't use this one for parsing (e.g. because of the "/" char in RTP/AVP..) So I have to define additional constants just to switch over the media transport protocol flag when parsing the media field.

I've considered using the "DESCRIPTION" attribute over each enum field, but then I have to write an additional method/extension method just to receive the enum flag description (gathering enum description attribute isn't a trivial task IMHO)

What's considered best practice to parse such data? Or is there something like a string enum and I'm just not aware of it?

public enum MyStringEnum {
    ENUMVAL1 = "EnumVal-01",
    ENUMVAL2 = "EnumVal-02"
    ...
}

Upvotes: 0

Views: 150

Answers (3)

Bob Vale
Bob Vale

Reputation: 18474

Actually the Name property of DisplayAttribute is probably the best way to go. You will find numerous examples of using this, quite often to populate dropdown combos.

I utility library I keep that has functions like this stored in it, meaning I only had to write the function once.

If you are desperate not to use an attribute then your best bet is to create a dictionary for your lookups.

 public static readonly Dictionary<string,MediaTransportProtocol> MediaTransportProtocols =
      new Dictionary<string,MediaTransportProtocol> {
          {"UDP", MediaTransportProtocol.UDP},
          {"RTP/AVP", MediaTransportProtocol.RTP_AVP},
          {"RTP_SAVP", MediaTransportProtocol.RTP_SAVP},
      };    

Then you can just perform the lookups and keep the advantages of using an enum in your code.

The ideal solution, which is what my library does, is to create a static generic class EnumHelper<T> that creates this dictionary in its static constructor by reflecting the enum to extract from the Display attribute, falling back on the member name. This means that reflection only happens once for each enum type.

Upvotes: 1

CrazyCasta
CrazyCasta

Reputation: 28302

Artur Udod has an interesting idea (#1). Another way to do do this would be to replace the '/' character with an underscore '_'. Then use the enum parse function.

tokenStr = tokenStr.replace('/', '_');
enumVal = Enum.Parse(typeof(MediaTransportProtocol), tokenStr);

I'm making an implicit assumption that your token character set is limited to letters, possibly digits and slashes. Obviously if there are two tokens of the form A_B and A/B that are to be considered differently, this would be a problem.

Upvotes: 1

Artur Udod
Artur Udod

Reputation: 4743

No. Enums are essentially ints.

let me give you few propositions:

1) use attributes on your enums

 public enum MyStringEnum {
        [ProtoFlagName("RTP/AVP")]
        ENUMVAL1 = 1,

        [ProtoFlagName("RTP/SAVP")]
        ENUMVAL2 = 2
        ...
 }

2) Chose a different data structure, for instance List<string> or Dictionary<MyStringEnum, string>

3) (don't like this one honestly). Use '_' symbol instead of '/'. Then just post-process your string values after you get them:

var stringValue = Enum.GetName(typeof(MyStringEnum ), MyStringEnum.ENUMVAL1);
var correctedStringValue = stringValue.Replace('_', '/');

Upvotes: 2

Related Questions