VB to .NET

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

  • 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.
  • In many cases, functional equivalence will be maintained, but the effort should be made to eliminate these casts to ensure cleaner code.

Source VB6

Public Enum HealthState
     Alive
     Dead
     Unknown
End Enum

Public Sub Kill(ByRef health As HealthState, Optional ByVal command As Integer = 1)
     health = command
End Sub

Target VB.NET

Public Enum HealthState
	Alive
	Dead
	Unknown
End Enum

Public Sub Kill(ByRef health As HealthState, Optional ByVal command As Integer = 1)
	health = command
End Sub

Target C#

public enum HealthState
{
	Alive,
	Dead,
	Unknown
}

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

 

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

public enum MyBoolean
{
   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:

public static void DeleteFile(MyBoolean delete)
{
if (delete == MyBoolean.False) return;
if (delete == MyBoolean.FileNotFound)
{
   throw new InvalidOperationException("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.

Enum.IsDefined method could have been used 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.

 

Talk To An Engineer