てくメモ

trivial な notes

【C#】辞書の key への列挙型の利用

enumを数値型にキャストして辞書の key にする、というコードを見たのをきっかけ。enumそのままとintにキャストした key で比較。

結論から言えば、単純な get/set のマイクロベンチマークでは有意な差はなかった。 レガシーな環境以外では実益はなさそう?

  • BenchmarkDotNet
  • .NET 7 と .NET Framework 4.8
  • インデクサによる get と set を確認する
[ShortRunJob(RuntimeMoniker.Net48)]
[ShortRunJob(RuntimeMoniker.Net70)]
[MemoryDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
public class EnumKeyBenchmark
{
    private KnownColor[] colors;
    private Dictionary<KnownColor, Color> enumDic;
    private Dictionary<int, Color> intDic;
    private int randomNumber;

    [GlobalSetup]
    public void Setup()
    {
        colors = (KnownColor[])Enum.GetValues(typeof(KnownColor));
        enumDic = colors.ToDictionary(v => v, v => Color.FromKnownColor(v));
        intDic = colors.ToDictionary(v => (int)v, v => Color.FromKnownColor(v));

        var rand = new Random();
        randomNumber = rand.Next(colors.Length);
    }

    [Benchmark(Baseline = true)]
    [BenchmarkCategory("Get")]
    public Color EnumKeyGet() => enumDic[colors[randomNumber]];
    [Benchmark]
    [BenchmarkCategory("Get")]
    public Color IntKeyGet() => intDic[(int)colors[randomNumber]];

    [Benchmark(Baseline = true)]
    [BenchmarkCategory("Set")]
    public Color EnumKeySet() => enumDic[colors[randomNumber]] = default;
    [Benchmark]
    [BenchmarkCategory("Set")]
    public Color IntKeySet() => intDic[(int)colors[randomNumber]] = default;
}
| Method     | Job                         | Runtime            | Mean     | Error    | StdDev   | Ratio | RatioSD | Allocated | Alloc Ratio |
|----------- |---------------------------- |------------------- |---------:|---------:|---------:|------:|--------:|----------:|------------:|
| EnumKeyGet | ShortRun-.NET 7.0           | .NET 7.0           | 11.14 ns | 4.309 ns | 0.236 ns |  1.00 |    0.00 |         - |          NA |
| IntKeyGet  | ShortRun-.NET 7.0           | .NET 7.0           | 11.89 ns | 2.528 ns | 0.139 ns |  1.07 |    0.01 |         - |          NA |
|            |                             |                    |          |          |          |       |         |           |             |
| EnumKeyGet | ShortRun-.NET Framework 4.8 | .NET Framework 4.8 | 15.65 ns | 2.017 ns | 0.111 ns |  1.00 |    0.00 |         - |          NA |
| IntKeyGet  | ShortRun-.NET Framework 4.8 | .NET Framework 4.8 | 15.86 ns | 0.301 ns | 0.016 ns |  1.01 |    0.01 |         - |          NA |
|            |                             |                    |          |          |          |       |         |           |             |
| EnumKeySet | ShortRun-.NET 7.0           | .NET 7.0           | 12.46 ns | 0.164 ns | 0.009 ns |  1.00 |    0.00 |         - |          NA |
| IntKeySet  | ShortRun-.NET 7.0           | .NET 7.0           | 13.99 ns | 8.514 ns | 0.467 ns |  1.12 |    0.04 |         - |          NA |
|            |                             |                    |          |          |          |       |         |           |             |
| EnumKeySet | ShortRun-.NET Framework 4.8 | .NET Framework 4.8 | 32.13 ns | 1.433 ns | 0.079 ns |  1.00 |    0.00 |         - |          NA |
| IntKeySet  | ShortRun-.NET Framework 4.8 | .NET Framework 4.8 | 31.45 ns | 2.553 ns | 0.140 ns |  0.98 |    0.00 |         - |          NA |