I have some better solution. The problem is very interesting an by far not so trivial as it may seem at first glance.
So, please see my article on enumerations:
Enumeration Types do not Enumerate! Working around .NET and Language Limitations[
^].
In the section 3.5, I explain the type
EnumerationIndexedArray<enumerationType, elementValueType>
and explain its implementation and usage. So, you can use this array in combination with the possibility to enumerate by enumeration type members (and not by values) I have introduced in my work.
Basically, this is what you can do:
protected enum BoxType
{
ftyp,
pdin,
moov,
}
EnumeraionIndexedArray<BoxType, uint> boxTypeValues =
new EnumeraionIndexedArray<BoxType, uint>();
Enumeration<BoxType> boxTypeEnumeration = new Enumeration<BoxType>();
foreach (EnumerationItem<BoxType> item in boxTypeEnumeration) {
uint intValue = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(item.Name), 0);
boxTypeEnumeration[item.EnumValue] = intValue;
}
From this moment, you have an object which provides the indexing interface like for arrays, but it is indexed by the values of your type
BoxType
. It is populated by the values you obtained using
BitConverter
; and the calculations are done only once. Every time you need this
uint
value, you just retrieve it from the
boxTypeValues
object you pre-populated as shown above. The time complexity is the same as indexing the regular array, O(1).
This completely solves your problem.
That was an interesting problem posed in an interesting way, I really appreciate it.
[EDIT]
Now, you have added that some string values which would not make valid member names, such as "©art". You should have told about them in the very beginning. And not what, should I suggest a workaround for you? Fortunately, this is not too hard to do. Your idea is anyway interesting enough, and, with my array indexed by enumeration values you can always add some work-around. Let's think.
Option #1:
First of all, you can introduce some unambiguous mechanism used to manually "decorate" such non-name strings into value names strings, with a function which would parse to "undecorate" them to get the correct value. For example,
Undecorate("_copy_art")
, or, say,
Undecorate("_A9_art")
may return "©art". Then the line shown above would be modified as
uint intValue =
BitConverter.ToUInt32(Encoding.ASCII.GetBytes(Undecorate(item.Name)), 0);
Simple enough, isn't it? I don't know your exact
character repertoire used to code your
uint
values as strings; if I knew it, it could be better. I think if the number of such exclusions as '©' is not so big, you will simply find out convenient "decoration" rule.
Option #2:
Of course, from the very beginning, the obvious solution would be
protected enum BoxType : uint
{
ftyp = valueFtyp,
pdin = valuePdin,
moov = valuePmoov,
}
but this is what you wanted to avoid from the very beginning. But combining this approach could give you another workaround. You could mix pre-calculated with automatically calculated values:
protected enum BoxType
{
ftyp,
pdin,
moov,
copyArt = someManuallyPrecalculatedValue,
somethingElse = someOtherPrecalculatedValue,
}
Now, part of enumeration member names code the
enum
values as before, and other names, such as
copyArt
, are manually pre-calculated. Now, you only need to populate the array the same was as before, but also take into account these two sorts of
enum members. How to tell them apart? For example, by the length of the member names, if you use longer names for manually pre-calculated
enum
names, as shown above. For example:
int autoCodedEnumerationMemberNameLength = 4;
foreach (EnumerationItem<BoxType> item in boxTypeEnumeration) {
uint intValue;
if (item.Name.Length > autoCodedEnumerationMemberNameLength)
intValue = (uint)item.Value;
else
intValue = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(item.Name), 0);
boxTypeEnumeration[item.EnumValue] = intValue;
}
That's all. You have two workaround option. Now you can chose one depending on your data.
—SA