普通类型和匿名类型有什么区别?

4

在C#中,普通类型和匿名类型在编译过程和运行时内存管理方面有何区别?匿名类型是否比普通类型更低效?


1
效率被定义为所产生价值与所消耗资源的比值。你关心什么价值和什么资源? - Eric Lippert
2个回答

12

来自MSDN

匿名类型 提供了一种方便的方式将一组只读属性封装到一个对象中,而无需先明确定义一个类型。类型名称由编译器生成,在源代码级别不可用。属性的类型由编译器推断。

备注:

匿名类型是从 object 直接派生的引用类型。编译器为它们赋予一个名称,但你的应用程序无法访问它。从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有区别,唯一的区别是除了 object 类型外,它不能被转换为任何其他类型


2
可以将它们分配给“动态”变量,但是除非它们被分配给对象或动态变量,否则它们不能离开它们创建的范围。然而,由于您无法将其从对象中转换回来,如果您想从函数返回匿名对象,则函数应该返回动态类型。 - ohmusama
3
你的观点虽然被广泛认为,但是是错误的。考虑以下函数:static T M<T>(Func<T> f) { return f(); } 现在调用它:var anon = M(()=>new { X = 1 }); 函数M创建并返回一个匿名类型对象,调用者成功将其保存到匿名类型的本地变量中,因此你所说的"除非转换为object或dynamic,否则它们无法离开它们创建的范围"的观点是错误的。 - Eric Lippert
1
但是,如果您不喜欢那个,那么这个怎么样:static T N<T>(T t) where T : class { return new { X = 123 } as T; } 然后 var y = N(new { X = 456 });。现在,N 明显返回一个新创建的对象,但从未将其转换为 objectdynamic,再次证明了您的说法是错误的。 - Eric Lippert
1
@EricLippert 语义,说真的。假设我有一个函数,我想在其中返回一个匿名对象,而不是“传递”它。在您的第一个示例中,您传递了一个生成它的函数,在第二个示例中,您笨拙地传递了一个具有相同原型的对象。我只是好奇如何在不在外部定义它的情况下得到一个对象?这就是我的观点,因为在函数外部定义它似乎是一个糟糕的用例。虽然我认为我可以看到它的用途... 它将是强类型的!! :) - ohmusama
1
@ohmusama:我是认真的。我在实际程序中使用过这种技术,通常称为“示例转换”。除了创建一个匿名类型之外,C#没有描述匿名类型的语法。因此,如果您希望以强类型方式传递一个匿名类型,则唯一的选择是在泛型方法上使用类型推断。类型推断需要一个示例来进行推断。因此:示例转换。 - Eric Lippert
显示剩余3条评论

3
关于内存管理,C#中普通类型和匿名类型之间有何区别?在某些方面,匿名类型是否比普通类型更低效?
就运行时而言,匿名类型只不过是带有构造函数、只读字段以及GetHashCodeToString实现的泛型内部类。就运行时而言,它们并没有任何特殊之处。运行时不知道它们是“匿名”的,运行时将其视为另一个类。生成的代码并不是什么有趣的东西。
关于编译过程,C#中普通类型和匿名类型之间有何区别?
我不知道这个问题想要问什么。

1
@guillegr123:好吧,像编译器开发人员一样思考。根据规范,您必须能够识别在同一程序集中两次使用“相同”的匿名类型,其中“相同”表示字段的数量、类型和名称相同且顺序相同。如果要跟踪两个(类型、名称)对列表是否相同,您将如何实现代码? - Eric Lippert
1
@guillegr123:它不仅可以被重复使用,语言规范要求必须重复使用。在这两行代码之后,您必须能够说a = b;并使其正常工作。此外,这不仅适用于方法内部,还适用于程序集内部。因此:鉴于此要求,您将如何实现编译器以便它能够确定两个匿名类型需要是相同的类型? - Eric Lippert
也许可以有一种类型字典,其中包含它们的定义,并在每次定义匿名类型时检查定义是否存在。如果是这样的话,我想在普通类型的情况下,检查完整名称就足够了,但在匿名类型的情况下,您必须检查完整定义。 - Guillermo Gutiérrez
1
@guillegr123:基本上是正确的,虽然仅检查全名对于类型来说是不够的。假设您的程序引用了两个都有名为Foo.Bar的类型的程序集。这是一种奇怪的情况,但是它是合法的;您可以使用extern别名来消除歧义。 但是我跑题了;是的,编译器维护一个字典,将(名称、类型)元组列表映射到表示类型的对象。这样做会消耗几个字节的内存,这就是您所问的。 - Eric Lippert
非常感谢 @Eric Lippert,您指出了一些非常有趣和重要的事情。 - Guillermo Gutiérrez
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接