I am writing code that has objects having integer member variables where the integer value has a specific constant meaning, which normally means "use an enum".
Suppose the values are the days of the week, Monday = 0, Tuesday = 1, and so on. (In my real case, there are several different "types" involved, some of which have 10-20 possible values.)
The code uses data objects which are auto-generated, and these data objects can only have certain, already specified types (int, string, bool, double), otherwise they could just use enums themselves. The question is, should I use an enum, or a struct with static readonly definitions and implicit casting. I favor the struct version.
Here is an example of using an enum:
enum Days { Monday = 0, Tuesday = 1, Wednesday = 2, Thursday = 3, Friday = 4, Saturday = 5, Sunday = 6, }
And here is my preferred struct code:
struct Day { readonly int day; public Day(int day) { this.day = day; } public static implicit operator int(Day value) { return value.day; } public static implicit operator Day(int value) { return new Day(value); } public static readonly Day Monday = 0; public static readonly Day Tuesday = 1; public static readonly Day Wednesday = 2; public static readonly Day Thursday = 3; public static readonly Day Friday = 4; public static readonly Day Saturday = 5; public static readonly Day Sunday = 6; }
My code frequently involves assigning values to the members of the data object. This means if I use the struct version, I can say for example Day myDay = dataObject.Day
rather than Days myDay = (Days)dataObject.Day
. With the amount of logic code that will be affected by this, I think the struct version is a win for readability because it removes a lot of explicit casts.
I don't want to just use plain int
s in my code because I like function signatures that indicate the purpose of the "int" being passed or returned. But I don't want the messiness that comes from casting enums all over.
I'm asking for arguments against the struct version. Would it disgust you if you found this pattern in code somewhere?
Clarification:
For the data objects to allow user types, other code which depends on the data objects would have to know about these types. The two "areas" of code are logically separate, and do not reference each other at all. I suppose a middle layer that separates the data objects from my code would be possible, but since all it would do is convert the enums to ints and back, it would be an awful lot of code to accomplish very little.
Another reason that these values sometimes must be represented as integers is that they are put through arithmetic operations sometimes. This is another place where explicit casting just gets annoying.
Finally, the definition of the possible values (days of week, in this example) is far less likely to change than the logic code. So conciseness and readability in the definition code isn't as valuable as in the logic code.
Days.Monday
? How is that not readable? Why wouldn't you want to use theDayOfWeek
enumeration that's already included in the framework? I don't understand your use-case at all. It's no different than if you had used an enum.\$\endgroup\$Days.Monday
isn't unreadable, but logic code filled with casts betweenDays
andint
is unreadable.\$\endgroup\$