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

如何定义类属性的枚举式类型?C#技术咨询

当然可以实现!

你想要的是强类型的属性选择器,同时具备IDE自动补全的能力——就像枚举那样方便地选属性,还能避免硬编码字符串的问题,这在C#里完全能做到,下面给你几种实用方案:

方案1:表达式树(最常用的强类型方案)

这是业界最流行的实现方式,既能享受IDE的自动补全,又能在编译时检查属性是否存在,完全杜绝运行时的属性名错误。

修改你的Faculty类代码如下:

public class Student 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Grade { get; set; } 
    public string Course { get; set; } 
} 

public class Faculty 
{
    // 先初始化示例数据,实际项目里替换成你的数据源
    private static List<Student> students = new List<Student>
    {
        new Student { ID = 1, Name = "张三", Grade = "高一", Course = "数学" }
    };

    public static string GetValue(int id, Expression<Func<Student, string>> propertySelector)
    {
        var student = students.FirstOrDefault(x => x.ID == id);
        if (student == null) return null;
        
        // 从表达式里解析出对应的属性
        var propertyMember = (MemberExpression)propertySelector.Body;
        var propertyInfo = (PropertyInfo)propertyMember.Member;
        
        return propertyInfo.GetValue(student)?.ToString();
    }
}

调用的时候,IDE会自动弹出Student的所有属性供你选择:

// 这里输入s.的时候,IDE会自动补全Name/Grade/Course等属性
var studentName = Faculty.GetValue(1, s => s.Name);

优点:强类型校验、完美补全、编译时错误检查;缺点:有一点点表达式解析的性能开销(绝大多数业务场景下可以忽略)。

方案2:nameof关键字 + 反射(简单高效)

如果你不需要强类型的属性引用,只是想避免硬编码字符串,同时保留IDE补全,用nameof关键字配合反射是最简单的方案。

修改GetValue方法:

public static string GetValue(int id, string propertyName)
{
    var student = students.FirstOrDefault(x => x.ID == id);
    if (student == null) return null;
    
    var propertyInfo = typeof(Student).GetProperty(propertyName);
    return propertyInfo?.GetValue(student)?.ToString();
}

调用时,nameof会自动给出Student的属性补全:

// nameof会弹出Student的属性列表,选完后编译时会把属性名转换成字符串
var studentGrade = Faculty.GetValue(1, nameof(Student.Grade));

优点:实现简单、性能比表达式树好;缺点:本质还是传递字符串,虽然nameof能保证编译时正确性,但如果有人直接写死字符串(比如"Grade"),还是会有运行时风险。

方案3:自定义“属性枚举”(类枚举语法)

如果你真的想要完全像枚举一样的语法(比如Student.Properties.Name),可以用Roslyn源码生成器自动生成对应的静态属性类。

源码生成器会在编译时扫描你的Student类,自动生成一个包含所有属性名的静态类,类似这样:

// 自动生成的代码,不需要手动写
public static class StudentProperties
{
    public const string ID = nameof(Student.ID);
    public const string Name = nameof(Student.Name);
    public const string Grade = nameof(Student.Grade);
    public const string Course = nameof(Student.Course);
}

然后调用的时候就和用枚举一样方便:

var studentCourse = Faculty.GetValue(1, StudentProperties.Course);

优点:语法完全像枚举、IDE补全完美、编译时生成无运行时开销;缺点:需要配置源码生成器(可以用现成的NuGet包,比如PropertyEnums.Generator,或者自己写简单的生成逻辑)。

总结

  • 追求强类型+编译时检查:优先用表达式树方案;
  • 追求简单高效:用nameof+反射;
  • 追求枚举式语法:用源码生成器生成属性枚举类。

这些方案都能满足你“调用时像枚举一样选属性、带补全”的需求,根据你的场景选最合适的就行~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:29:48