C# 匿名类型使用方法 C#如何创建和使用匿名类型

来源:这里教程网 时间:2026-02-21 17:39:55 作者:

匿名类型只能用 var 声明,不能显式写类型名

匿名类型的本质是编译器自动生成的只读类,没有公开的类型名。试图写

AnonymousType x = new { Name = "a", Age = 25 };
会编译失败——
AnonymousType
根本不存在。必须用
var
让编译器推断类型:
var person = new { Name = "a", Age = 25 };

常见错误:在方法返回值、字段或参数中尝试使用匿名类型,比如

public {string Name} GetData()
private {int Id} _cache;
,这些全部非法。匿名类型作用域仅限于当前方法内,且不能跨方法传递(除非转成
object
,但会丢失编译时成员访问能力)。

属性名和类型由初始化表达式决定,大小写敏感且不可修改

new { Name = "Tom", age = 18 }
会生成两个属性:
Name
string
)和
age
int
),注意
age
是小写,调用时也必须写
obj.age
,写
obj.Age
就报错
CS1061 'object' does not contain a definition for 'Age'

以下情况会触发新类型生成(即两个匿名对象不兼容):

属性名顺序不同:
new { A = 1, B = 2 }
new { B = 2, A = 1 }
是不同类型
属性名相同但类型不同:
new { X = 5 }
int
) vs
new { X = 5L }
long
一个带属性,一个不带:
new { Id = 1 }
new { Id = 1, Name = "x" }

可安全用于 LINQ 查询投影,但慎用于跨方法或序列化

匿名类型最自然的使用场景是 LINQ 的

Select
投影,例如:

var result = users.Where(u => u.IsActive)
                  .Select(u => new { u.Id, u.Name, IsAdult = u.Age >= 18 });

这时

result
IEnumerable
,每个元素都是同一匿名类型,可正常遍历和访问属性。

但要注意:

不能直接 JSON 序列化(如
JsonSerializer.Serialize(obj)
可能抛
NotSupportedException
,取决于序列化器配置)
反射获取属性需用
obj.GetType().GetProperties()
,不能硬编码类型
若需跨方法传参,应改用元组(
(string Name, int Age)
)、记录类型(
record
)或普通类

Equals 和 GetHashCode 基于所有属性值,但不支持 null 安全比较

两个匿名对象只要所有属性名、类型、值都相同,

==
.Equals()
就返回
true
。例如:

var a = new { X = 1, Y = "hello" };
var b = new { X = 1, Y = "hello" };
Console.WriteLine(a.Equals(b)); // true

但一旦任一属性为

null
,且另一方对应属性是非空引用类型,比较仍成立;而如果双方都是
null
,也没问题。真正容易出错的是嵌套匿名类型或含数组时——数组本身不会被深度比较,
new { Data = new[] { 1, 2 } }.Equals(new { Data = new[] { 1, 2 } })
返回
false
,因为数组引用不同。

所以别依赖匿名类型的相等性做关键逻辑判断,尤其涉及集合去重或缓存键计算时,优先用明确的

record
或自定义
IEquatable<t></t>
实现。

相关推荐