Skip to content

EqualityComparer<TEnum?>.Default allocates #67842

Closed
@ltrzesniewski

Description

@ltrzesniewski

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.

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions