Why is it that non-integral enums cannot be created? I want to know if this is a language design decision, or if there are issues with implementing this in the compiler.
I think enums were made this way because, as opposed to what you want to do, enumerations weren't meant to hold any meaningful numerical representation.
For example, enums are perfect for describing the ff:
enum Color
{
Black,
White,
Red,
Yellow,
Blue,
//everything else in between
}
(admittedly color can be represented by complex types numerically, but indulge me for the moment). How about mood?
enum Mood
{
Happy,
Giddy,
Angry,
Depressed,
Sad
}
or taste?
enum Taste
{
Bitter,
Salty,
Sweet,
Spicy
}
I think you get the point. Bottomline is: enumerations were meant to represent objects or object characteristics that are difficult to represent numerically, or do not have meaningful or practical numerical representations -- and thus the arbitrary assignment to an integer which is the most convenient data type for such.
This is as opposed to things like holidays, which are numerically meaningful.
Without knowing the actual answer, I'd suggest that it's more the latter - there's no real justifiable need.
Enums in my mind are simply there to represent the various options available in a particular case; not to actually store data.
A variable holding an enum value shouldn't be thought of as holding the value 1 or 2 or 3, even if those are the actual values stored in that memory location. It should be thought of as representing Monday, Tuesday or Wednesday (for example) instead. It only has meaning in terms of that enumeration and really shouldn't (although often does) be used in other ways. Operations you perform on Enum values are simply programming shortcuts made available by the way Enums have been implemented.
Only the designers of the language can tell you why they didn't allow for non-integral enumerations but I can tell you the most likely explanation.
The original C didn't do it because it was unnecessary for its purposes (a systems programming language). C++ didn't do it since it was based on C and you could emulate it with classes anyway. C# probably doesn't do it for the same reasons.
This is just guesswork on my part since I wasn't involved in the design of any of those languages.
Once you've decided to go the way of classes (DateTime), there's little reason to not go all the way. If you want to use enum's, you can create the enums as sequential integers starting with zero and have an array of DateTime values using those enums as indexes.
But I'd just have a Holiday class which provided the whole kit and kaboodle within the class: the constants, the get() routine to return a DateTime based on those constants and so on.
That gives you true encapsulation and the ability to chage the implementation totally without affecting the interface. Why toss away one of the benefits of OOP?
There's no technical reason why it couldn't be done, but then, we are really more talking about a set of constants (perhaps within a common namespace, if they're related).
In an enum, the numerical value is generally secondary.
In the following:
enum Fruit {
Apple,
Orange,
Pear,
Peach
}
we are only describing a set of named constants. We are saying that a variable of type Fruit can take one of these four values. What the integer value of each one is, is really not relevant. As long as I only refer to them by name, it doesn't matter if the value representing Apple is 0, 1, 32, -53 or 0.002534f.
Most languages do allow you to specify the value that should represent each, but that's really secondary. It's sometimes useful, but it's not part of the core purpose with enums. They are simply there to give you a set of related named constants without having to specify an integer ID for each.
Further, enums are often used to specify optional flags that can be combined with bitwise operations. That is trivial to implement if each value is represented by an integer (then you just have to pick an integer that uses the bit pattern you want). Floating-point values wouldn't be useful in this context. (bit-wise and/or operations don't make much sense on floating-point values)