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

如何按声明顺序获取匿名类型的所有属性名称?

获取匿名类型属性声明顺序的可靠方法

首先得明确:C#规范里明确规定了匿名类型的属性顺序与声明顺序完全一致,问题在于常规反射方法(比如Type.GetProperties)的返回顺序没有官方保障,而TypeInfo.DeclaredProperties虽然当前可能返回正确顺序,但同样没有明确的官方承诺,所以得找基于编译器生成规则的可靠方案。

下面是两种经过验证的可靠实现方式:

方法1:利用表达式树的NewExpression成员顺序

编译器在生成匿名类型的表达式时,会严格保留属性的声明顺序,我们可以通过表达式树提取这个顺序:

using System.Linq.Expressions;

public static List<string> GetAnonymousPropertyOrder<T>(T anonymousInstance)
{
    // 创建一个返回自身的lambda表达式,其Body是NewExpression类型
    var parameter = Expression.Parameter(typeof(T), "x");
    var lambda = Expression.Lambda<Func<T, T>>(parameter, parameter);
    var newExpr = (NewExpression)lambda.Body;
    
    // NewExpression.Members的顺序就是匿名类型的属性声明顺序
    return newExpr.Members.Select(m => m.Name).ToList();
}

使用示例:

var person = new { Name = "Bob", Age = 28, City = "New York" };
var propertyOrder = GetAnonymousPropertyOrder(person);
// propertyOrder会是 ["Name", "Age", "City"]

这个方法的可靠性来源于C#编译器的生成规则——匿名类型的构造表达式(NewExpression)的成员顺序完全匹配声明顺序,这是规范明确要求的,不会随CLR版本变化而改变。

方法2:通过构造函数参数顺序获取

匿名类型只会生成一个构造函数,其参数顺序与属性声明顺序完全一致,且参数名就是属性名,我们可以利用这一点:

public static List<string> GetAnonymousPropertyOrder<T>()
{
    // 匿名类型只有一个构造函数
    var constructor = typeof(T).GetConstructors().Single();
    // 构造函数参数的顺序就是属性声明顺序,参数名等于属性名
    return constructor.GetParameters().Select(p => p.Name).ToList();
}

使用示例:

var person = new { Name = "Bob", Age = 28, City = "New York" };
var propertyOrder = GetAnonymousPropertyOrder<typeof(person)>();
// 或者直接传入实例的类型,强类型方式更可靠

这种方法同样可靠,因为C#规范要求匿名类型的构造函数参数顺序必须匹配属性声明顺序,参数名与属性名一致,这是编译器必须遵守的规则。

为什么不推荐TypeInfo.DeclaredProperties?

虽然在当前的.NET实现中,TypeInfo.DeclaredProperties可能会按声明顺序返回属性,但微软的官方文档从未明确承诺这个顺序的稳定性——反射API的返回顺序通常被定义为“未指定”,未来CLR的反射实现可能会调整这个顺序,所以不能作为可靠依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:21:32