-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
EqualityComparer<TEnum?>.Default (when T is a nullable enum) is resolved to ObjectEqualityComparer<TEnum?>, which boxes the enum when performing equality comparison. This causes an unnecessary allocation.
Here is a reproduction:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ConsoleApp;
public static class Program
{
public static void Main()
{
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday); // Warm-up
var before = GC.GetAllocatedBytesForCurrentThread();
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday);
var after = GC.GetAllocatedBytesForCurrentThread();
Console.WriteLine(RuntimeInformation.FrameworkDescription);
Console.WriteLine(after > before ? "Allocates" : "Allocation-free");
}
}This results in:
.NET 7.0.0-preview.2.22152.2
Allocates
If you replace DayOfWeek? with DayOfWeek, or if you use a type such as int? instead, the code will print Allocation-free.
Configuration
I reproduced this on .NET 6 and on .NET 7 preview 2 on Windows x64, but this should be independent of the OS and architecture.
Regression?
This is not a regression. It also reproduces on .NET Framework 4.8.
Analysis
This is roughly due to the fact that ComparerHelpers.CreateDefaultEqualityComparer special-cases both Nullable<T> and enums, but does not special-case nullable enums. This code path ends up using ObjectEqualityComparer<T>.
I'm willing to provide a PR to fix this if you'd like.