WARNING #6021

    Casting 'int' to Enum may cause different behavior.

    Description

    Enum's in .Net are integral types and therefore any valid integral value can be cast to an Enum type. This is still possible even when the value being cast is outside of the values defined for the given enumeration!

    Thus, when mixing integers with Enums it is possible to create invalid Enumeration instances that do not reference any of the defined values for that Enumeration.

    Recommendations

    To better illustrate this issue, here's an example from C#:

    publicenumMyBoolean
    {
    True = -1,
    False = 0,
    FileNotFound = 1
    }

    In this case there are three defined values for MyBoolean: True (-1), False (0) and FileNotFound (-1). It is often times assumed that a variable of type MyBoolean will only hold one of these three values. This is incorrect!

    The following statement is valid C#, and it does not throw any kind of Exception during run time.

    MyBoolean b = (MyBoolean)45;

    In this case, b will have a value of 45 and will not be a defined value for MyBoolean. However, in cases where code has not followed best practices this can lead to errors that hurt functional equivalence.

    For example:

    publicstaticvoid DeleteFile(MyBoolean delete)
    {
    if (delete == MyBoolean.False) return;
    if (delete == MyBoolean.FileNotFound)
    {
    thrownewInvalidOperationException("File does not exist.");
    }
    File.Delete("important.log");
    }

    In this case, the developer assumed that only if delete was MyBoolean.True would the code reach the File.Delete statement. Such constructions can be common.

    One possible workaround is to use the Enum.IsDefined() method to verify if a given integral value is defined for a given Enumeration. This method however will not work for enumerations marked with the Flags attribute and which are used as a bit map.

    Additionally, one can ensure logic checks explicitly for defined Enum values and does not assume Enum-typed variables will conform to the defined list of values.

    Finally, in many cases functional equivalence will be maintained, but effort should be made to eliminate these casts to ensure cleaner code.

    Sample VB6

    PublicEnum HealthState
         Alive
         Dead
         Unknown
    EndEnum

    PublicSub Kill(ByRef health As HealthState, OptionalByVal command AsInteger = 1)
         health = command
    EndSub

    Target VB.NET

    PublicEnum HealthState
         Alive
         Dead
         Unknown
    EndEnum

    PublicSub Kill(ByRef health As HealthState, ByRef command AsInteger)
         health = command
    EndSub

    Expected VB.NET

    The expected code will depend on each case, but for this case this might be a viable solution:

    PublicSub Kill(ByRef health As HealthState, ByRef command AsInteger)
        If command = 1 Then
              health = HealthState.Dead
        EndIf
    EndSub

    Another solution, that more closely resembles the original would be:

    PublicSub Kill(ByRef health As HealthState, ByRef command AsInteger)
          If [Enum].IsDefined(GetType(HealthState), command) Then
             health = HealthState.Dead
          EndIf
    EndSub

    Target C#

    publicenumHealthState
    {
        Alive ,
        Dead ,
        Unknown
    }

    staticpublicvoid Kill(ref HealthState health, int command)
    {
        //UPGRADE_WARNING: (6021) Casting 'int' to Enum may cause different behaviour.
        health = (HealthState) command;
    }

    Expected C#

    The expected code will depend on each case, but for this case this might be a viable solution:

    staticpublicvoid Kill(ref HealthState health, int command)
    {
         if (command == 1)
        {
            health = HealthState.Dead;
        }
    }

    Another solution, that more closely resembles the original would be:

    staticpublicvoid Kill(ref HealthState health, int command)
    {
         if (Enum.IsDefined(typeof(HealthState)
    , command))
         {
              health = (HealthState) command;
         }
    }


    Download VBUC Free Trial
    Download VBUC Now

    It's time to eradicate VB6
    ROI of eradicating VB6

    8 Proven Tips for
    Planning a Successful Migration

    8 Tips for migration