如何在外部获取带约束泛型类的属性名称?
如何从带约束的泛型类中获取属性名称?
我定义了如下简单类:
class Simple { //... }
还定义了一个带约束的泛型类:
class Generic<T> where T : Simple, new() { public T SimpleObject { get; set; } public string Type { get; set; } }
我想获取Generic<T>中Type属性的名称,尝试用Console.WriteLine(nameof(Generic.Type));时,编译器报错“使用泛型类型需要1个类型参数”。添加<>或者<object>也不行,因为object不满足T的约束。不想硬编码属性名(魔术字符串),避免后续重命名属性时出现不同步的bug,需要在Generic类外部(比如Program.cs)调用相关代码。
可行解决方案
1. 使用符合约束的具体类型参数
因为Simple本身满足Generic<T>的约束(是Simple的子类、有无参构造),直接用它作为类型参数即可:
Console.WriteLine(nameof(Generic<Simple>.Type));
这种方式最直接,编译器能正确识别,且属性重命名时nameof会自动同步更新。
2. 创建空派生类规避泛型参数
如果不想在代码中直接依赖Simple类型,可以创建一个继承自Generic<Simple>的空派生类:
class DummyGeneric : Generic<Simple> { }
之后就可以通过这个派生类获取属性名:
Console.WriteLine(nameof(DummyGeneric.Type));
后续只要Generic<T>的约束不变,这个空类无需修改就能正常使用。
3. 表达式树方式(适合复杂场景)
如果需要更灵活的方式,比如不知道具体的约束类型时,可以用表达式树提取属性名:
public static string GetPropertyName<T>(Expression<Func<T, object>> expression) { if (expression.Body is MemberExpression memberExpr) return memberExpr.Member.Name; if (expression.Body is UnaryExpression unaryExpr && unaryExpr.Operand is MemberExpression operandMember) return operandMember.Member.Name; throw new ArgumentException("Invalid expression"); }
调用时传入符合约束的类型:
Console.WriteLine(GetPropertyName<Generic<Simple>>(x => x.Type));
这种方式代码量稍大,但扩展性更强。
为什么原写法不行?
nameof无法直接作用于未绑定的泛型类型(即未指定类型参数的Generic),必须提供一个满足泛型约束的有效类型参数,编译器才能解析对应的成员。
内容的提问来源于stack exchange,提问作者Cornelis
相关产品推荐
相关产品推荐

