Common Type System—Type Safety Limitations
Type Safety Limitations
I’ve mentioned a couple times now that enums add type safety where traditionally out-of-range numbers
could be passed in instead. But this is subtly misleading. Because an enum is nothing but a simple primitive
data type underneath, instances can be manufactured that hold values with no name mapping. In the
example at the beginning of this section with the Color enum with Red (0), Green (1), and Blue (2), for
example, we can create an instance that has a value of 3!
Color MakeFakeColor() { return (Color)3; }
There’s not much you can do to prevent this. All you can do is to take precautions when accepting an
enum instance from an untrusted source. For example, if you’ve authored a public API that takes an
enum as input, it must always check that it is in the valid range before operating on it. To aid you in this
task, the System.Enum type defines a static helper method, IsDefined. It returns a Boolean value to
indicate whether the supplied value is inside the defined range for the specific enum:
void AcceptColorInput(Color c) { // Ensure we check the input enum value for validity. if (!Enum.IsDefined(typeof(Color), c)) throw new ArgumentOutOfRangeException(“c”); // OK to work with the input here, we’ve validated it. // ... }
If somebody were to call AcceptColorInput with an intentionally invalid instance of Color, the
method would throw an exception instead of failing in an unpredictable way:
AcceptColorInput(MakeFakeColor());
This approach doesn’t quite work with flags enums. An instance of a flags enum that represents a combination of values will not itself be a valid selection from the range of the enum’s values. But usually this is acceptable. Presumably, the method body won’t be doing a switch or a check for precise equality. Instead, all of its bitwise checks will fail, probably leading it to a branch of program logic where a failure is initiated in a controlled manner.
|

