Recipe1.18.Testing for a Valid Enumeration Value


Recipe 1.18. Testing for a Valid Enumeration Value

Problem

When you pass a numeric value to a method that accepts an enumeration type, it is possible to pass a value that does not exist in the enumeration. You want to perform a test before using this numeric value to determine if it is indeed one of the ones defined in this enumeration type.

Solution

To prevent this problem, test for the specific enumeration values that you allow for the enumeration-type parameter using a switch statement to list the values.

Using the following Language enumeration:

 enum Language {     Other = 0, CSharp = 1, VBNET = 2, VB6 = 3 } 

Suppose you have a method that accepts the Language enumeration, such as the following method:

 public void HandleEnum(Language language) {     // Use language here… } 

You need a method to define the enumeration values you can accept in HandleEnum. The CheckLanguageEnumValue method shown here does that:

 public static bool CheckLanguageEnumValue(Language language) {     switch (language)     {         // All valid types for the enum listed here         // This means only the ones we specify are valid.         // Not any enum value for this enum         case Language.CSharp:         case Language.Other:         case Language.VB6:         case Language.VBNET:              break;         default:         Debug.Assert(false, language +             " is not a valid enumeration value to pass.");         return false;     }     return true; } 

Discussion

Although the Enum class contains the static IsDefined method, it should not be used. IsDefined uses reflection internally, which incurs a performance penalty. Also, versioning of the enumeration is not handled well. Consider the scenario in which you add the value MgdCpp (managed C++) to the Languages enum in the next version of your software. If IsDefined is used to check the argument here, it will allow MgdCpp as a valid value, since it is defined in the enumeration, even though the code for which you are validating the parameter is not designed to handle it. By being specific with the switch statement shown in CheckLanguageEnumValue, you reject the MgdCpp value and the code does not try to run in an invalid context. This, after all, is what you were after in the first place.

The enumeration check should always be used whenever the method is visible to external objects. An external object can invoke methods with public visibility, so any enumerated value passed in to this method should be screened before it is actually used.

Methods with internal, protected, and internal protected visibility have a much smaller scope than public methods, but can still suffer from the same problems as the public methods. Methods with private visibility may not need this extra level of protection. Use your own judgment on whether to use the CheckLanguageEnumValue method to evaluate enumeration values passed in to private methods.

The HandleEnum method can be called in several different ways. Three of these are shown here:

 HandleEnum(Language.CSharp) HandleEnum((Language)1) HandleEnum((Language)someVar) // Where someVar is an int type 

Any of these method calls is valid. Unfortunately, the following method calls are also valid:

 HandleEnum((Language)100) int someVar = 100; HandleEnum((Language)someVar) 

These method calls will also compile without errors, but odd behavior will result if the code in HandleEnum tries to use the value passed in to it (in this case the value 100).In many cases an exception will not even be thrown; HandleEnum just receives the value 100 as an argument, as if it were a legitimate value of the Language enumeration.

The CheckLanguageEnumValue method prevents this from happening by screening the argument for valid Language enumeration values. The following code shows the modified body of the HandleEnum method:

 public void HandleEnum(Language language) {     if (CheckLanguageEnumValue(language))     {         // Use language here…     }     else     {         // Deal with the invalid language value here…     } } 

See Also

To test for a valid enumeration within an enumeration marked with the Flags attribute, see Recipe 1.19.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net