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.