Open7

Enumの構文解析に特別扱いがあるっぽい話

ピン留めされたアイテム

当初はnullableなenumのcaseラベルでコンパイルエラー起こしたとこから

絶対他に誰か踏んでそうに思うのだが、探し方が悪いのか全然情報が見つからない
試したキーワード C# nullable enum case issue 辺り
環境はNet Core3.1 C#8
.NET5 C#9 でも同様だった

これはOK

class TestClass
{
    public TestEnum TestEnum { get; set; }

    public void Hoge()
    {
        switch (TestEnum)
        {
            case TestEnum.Item1:
            case TestEnum.Item2:
            case TestEnum.Item3:
            case TestEnum.Item4:
            default:
                break;
        }
    }

    public void Fuga()
    {
        var n = TestEnum switch
        {
            TestEnum.Item1 => "1",
            TestEnum.Item2 => "2",
            TestEnum.Item3 => "3",
            TestEnum.Item4 => "4",
            _ => ""
        };
    }
}

public enum TestEnum
{
    Item1, Item2, Item3, Item4
}

これはNG

class TestClass
{
    public TestEnum? TestEnum { get; set; }

    public void Hoge()
    {
        switch (TestEnum)
        {
            case TestEnum.Item1: // エラー (TestEnumがプロパティを参照する)
            case TestEnum.Item2: // 同上
            case TestEnum.Item3: // 同上
            case TestEnum.Item4: // 同上
            default:
                break;
        }
    }

    public void Fuga()
    {
        var n = TestEnum switch
        {
            TestEnum.Item1 => "1", // エラー (TestEnumがプロパティを参照する)
            TestEnum.Item2 => "2", // 同上
            TestEnum.Item3 => "3", // 同上
            TestEnum.Item4 => "4", // 同上
            _ => ""
        };
    }
}

これはOK (=nullableなenumがラベルに使えないというわけではない)

class TestClass
{
    public TestEnum? TestEnumProp { get; set; }

    public void Hoge()
    {
        switch (TestEnumProp)
        {
            case TestEnum.Item1:
            case TestEnum.Item2:
            case TestEnum.Item3:
            case TestEnum.Item4:
            default:
                break;
        }
    }

    public void Fuga()
    {
        var n = TestEnumProp switch
        {
            TestEnum.Item1 => "1",
            TestEnum.Item2 => "2",
            TestEnum.Item3 => "3",
            TestEnum.Item4 => "4",
            _ => ""
        };
    }
}

一番影響が少なそうな回避策

using ETestEnum = ...TestEnum;

……

class TestClass
{
    public ETestEnum? TestEnum { get; set; }

    public void Hoge()
    {
        switch (TestEnum)
        {
            case ETestEnum.Item1:
            case ETestEnum.Item2:
            case ETestEnum.Item3:
            case ETestEnum.Item4:
            default:
                break;
        }
    }

    public void Fuga()
    {
        var n = TestEnum switch
        {
            ETestEnum.Item1 => "1",
            ETestEnum.Item2 => "2",
            ETestEnum.Item3 => "3",
            ETestEnum.Item4 => "4",
            _ => ""
        };
    }
}


public enum TestEnum
{
    Item1, Item2, Item3, Item4
}

・enum以外で似たようなことやろうとすると全部死ぬ (例:intでプロパティ作って同名クラスのconst参照)
・anotationでクラス参照しようとした場合も同名プロパティがあればそちらが優先される
上から考えるとswitchの構文解析の際に条件がenumの場合だけ特殊な処理が入っていると考えるのが妥当?

switchに限らずenumの構文解析に特別扱いがあるのでは?

TestEnum TestEnum = TestEnum.Item1; // OK
TestEnum? TestEnum = TestEnum.Item1; // NG
int TestEnum = TestEnum.Item1 // NG
var TestEnum = TestEnum.Item1 // NG
ログインするとコメントできます