You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中实现类似Delphi的枚举关联数据编译检查?

实现C#枚举成员缺失关联数据时的编译报错

需求背景

在Delphi中可定义枚举类型TMyEnum及关联的TInfo记录常量数组MyEnumDetails,新增枚举成员时编译器会直接报错,强制开发者补全关联数据。现需在VS2022的.NET 6 C#代码中实现同样效果:新增枚举成员但未补充对应关联数据时,编译器直接报错。

已尝试的方法及问题

  • 使用Dictionary初始化:遗漏枚举成员时无任何警告或错误
  • 遍历枚举结合switch语句添加数据:未触发CS8509等预期的穷尽检查警告
  • 将switch移至单独方法GetInfo:最初出现CS0161(未返回所有代码路径的值)错误,但添加default分支或外部return后,遗漏枚举成员时不再有提示
  • 已确认csproj文件和IDE选项中未禁用相关警告

问题

  1. 为什么上述尝试无法触发预期的遗漏枚举成员警告?
  2. 有没有其他方法可以实现枚举成员缺失关联数据时编译报错的目标?

可行解决方案

方案1:利用C# 8.0+的switch表达式穷尽检查

定义返回关联数据的方法,使用无default分支的switch表达式,同时确保枚举未标记Flags特性(Flags会干扰穷尽检查逻辑)。示例代码:

public enum MyEnum
{
    Member1,
    Member2,
    // 新增Member3时,编译器会直接抛出CS8509错误
}

public record Info(string Name, int Value);

public static Info GetEnumInfo(MyEnum enumValue)
{
    return enumValue switch
    {
        MyEnum.Member1 => new Info("成员1", 100),
        MyEnum.Member2 => new Info("成员2", 200),
        // 新增枚举成员后,此处会触发CS8509:switch表达式未覆盖所有可能的输入值
    };
}

新增枚举成员但未补充switch分支时,编译器会直接报错,强制补全关联数据。

方案2:自定义Roslyn代码分析器

如果需要更灵活的检查逻辑(比如关联数据存储在数组或字典中),可以编写自定义Roslyn分析器:

  • 遍历枚举的所有成员
  • 检查每个成员是否存在对应的关联数据
  • 对未匹配的成员抛出自定义编译错误

该方式适合复杂场景,但需要编写和部署自定义分析器。

方案3:.NET 7+静态构造函数检查(配合单元测试)

在.NET 7及以上版本,可在静态构造函数中遍历枚举成员,检查每个成员是否有对应数据,遗漏则抛出运行时异常;再配合单元测试在构建阶段执行该逻辑,提前发现问题:

public static class EnumInfoStore
{
    private static readonly Dictionary<MyEnum, Info> _details = new()
    {
        { MyEnum.Member1, new Info("成员1", 100) },
        { MyEnum.Member2, new Info("成员2", 200) }
    };

    static EnumInfoStore()
    {
        var allMembers = Enum.GetValues<MyEnum>();
        foreach (var member in allMembers)
        {
            if (!_details.ContainsKey(member))
            {
                throw new InvalidOperationException($"枚举成员{member}未添加关联数据");
            }
        }
    }

    public static Info GetInfo(MyEnum value) => _details[value];
}

添加单元测试调用EnumInfoStore.GetInfo,构建时执行测试即可提前发现遗漏问题。


无法触发警告的原因

  1. Dictionary初始化:C#编译器不会检查字典键是否覆盖所有枚举成员,这属于开发者自主维护的逻辑,编译器不做强制校验。
  2. 遍历枚举+switch:循环中的switch语句,编译器无法确认循环是否覆盖了所有枚举成员,因此不会触发穷尽检查警告。
  3. 带default分支的switch方法:添加default分支后,编译器认为所有代码路径都有返回值,会终止穷尽检查,新增枚举成员时不再报错。

内容的提问来源于stack exchange,提问作者OBones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:05:30