C# enum.ToString() boxing: resolve or supress?

Viewed 1834

So recently we've installed the 'Clr Heap Allocation Analyzer' extension for Visual Studio to check our code for heap allocation problems caused by boxing, among others. We've come across the warning 'HAA0102', which gives the following description:

Non-overridden virtual method call on a value type adds a boxing or constrained instruction

It refers to the condition checks in following line of code:

if(instanceType == Enums.Tags.DialoguePanel.ToString())
{
     // Some code handling
}
else if(instanceType == Enums.Tags.InfoPanel.ToString())
{
    // Some other code handling
}

For context, the Enums.Tags.DialoguePanel refers to the following enum declaration:

public enum Tags
        {
            InfoPanel,
            DialoguePanel,
            WarningPanel
        }

Now I understand that enum is a value type and therefore Enums.Tags.DialoguePanel is a value type. I also understand that to .ToString() is basically boxing that to a reference type (string).

My question is whether or not it is necessary to refactor these kinds of lines to avoid boxing (and if so... how?) or if it's better to suppress this warning for these specific cases? Please keep in mind that that we do need to keep the enum types. They're used as a controlled way of providing the user options (in a dropdown list). Refactoring those to be of another type will take a LOT of work (which is fine if the performance will be increased significantly).

Thanks in advance!

2 Answers

Enum has certain advantages over String, namely that you're adding a constraint that only valid values can be among the defined enums. Understandably, your web server receives strings, not enum values, but the proper approach should be to force the string into an enum value, and then compare enum values.

The forcing of the string value of course can go wrong, so this should be considered a "validation step". However once the enum value is valid, you won't encounter problems of this nature, which in addition to being a bit of a performance drop is also error-prone in my humble opinion (what happens if you expect value to match one of the enum values and none do?).

// "Validation"
instanceType = (Enums.Tags) Enum.Parse(typeof(Enums.Tags), value)

// Usage
if(instanceType == Enums.Tags.DialoguePanel)
{
     // Some code handling
}
else if(instanceType == Enums.Tags.InfoPanel)
{
    // Some other code handling
}

Now I understand that enum is a value type and therefore Enums.Tags.DialoguePanel is a value type. I also understand that to .ToString() is basically boxing that to a reference type (string).

That's not quite true. The boxing is because Enum.ToString calls the Enum.GetValue method, which returns the underlying value as an object - hence the boxing operation. The string is a reference type so it is not boxed. And just because of the string conversion no boxing would be necessary.

And yes, we receive strings from a web server. Although we can try to parse the string into an enum value, the performance drop would not be desirable, obviously.

I actually created once a generic Enum<TEnum> class for enum operations without boxing. And though the no-boxing Enum<TEnum>.ToString is about 20 times faster (at least in this .NET Fiddle test), I think the performance loss caused by the boxing compared to the web server response times are negligible so you can just suppress the warning. But feel free to give it a try if you wish.

Related