关于结构的问题

时间:2009-03-20 18:02:05

标签: c# class struct language-specifications

MSDN说,一个16字节或更少的类将更好地作为结构[citation]处理。
那是为什么?
这是否意味着如果一个结构超过16个字节,它的效率低于一个类或它是否相同? 你如何确定你的班级是否在16字节以下? 是什么限制了结构体像一个类一样? (除了禁止无参数构造函数)

7 个答案:

答案 0 :(得分:6)

这个问题有几个不同的答案,它有点主观,但我能想到的一些原因是:

  • 结构是值类型,类是引用类型。如果你使用16个字节作为总存储空间,那么为每个存储器引用创建内存引用(4到8个字节)可能是不值得的。
  • 当你有非常小的对象时,它们通常可以被推到IL堆栈上,而不是对象的引用。这可以真正加速一些代码,因为你正在消除被叫方的内存取消引用。
  • IL中的类有一些额外的“绒毛”,如果你的数据结构非常小,无论如何都不会使用这些漏洞,所以它只是你不需要的额外垃圾。

结构和类之间最重要的区别是结构是值类型,类是引用类型。

答案 1 :(得分:3)

通过“高效”,他们可能正在讨论表示类或结构所需的内存量。

在32位平台上,分配对象至少需要16个字节。在64位平台上,最小对象大小为24个字节。因此,如果您纯粹根据所使用的内存量来查看它,那么包含少于16个字节数据的结构将比相应的类“更好”。

但是使用的内存量并不是全部。值类型(结构)与引用类型(类)根本不同。结构可能不方便使用,如果你不小心,实际上可能会导致性能问题。

当然,真正的答案是使用在您的情况下最好的方法。在大多数情况下,使用课程会更好。

答案 2 :(得分:2)

检查此链接,我今天在其中一个答案中找到了它:.NET Type Internals。您还可以尝试在结构和类之间搜索SO和Google搜索“引用类型与值类型”。

  
    

什么限制结构体像一个类一样行事?

  

有许多不同之处。例如,您不能从结构继承。

您不能拥有虚方法,因此您无法使用结构来实现接口。结构中的实例方法可以访问struct的私有字段,但除此之外,它们的行为很像辅助“辅助”函数(对于不可变的结构,它们有时甚至不需要访问私有数据)。所以我发现它们并不像课堂方法那样“有价值”。

答案 3 :(得分:0)

在内存中,struct将直接保存数据,而类的行为更像是指针。仅这一点就产生了重要的区别,因为将结构作为参数传递给方法将传递其值(将它们复制到堆栈上),而类将传递对值的引用。如果结构很大,您将在每个方法调用上复制很多值。当它真的很小时,复制值并直接使用它们可能比复制指针更快,不得不从另一个地方抓取它们。

关于限制:您不能将其指定为null(尽管您可以使用Nullable<>)并且您必须立即对其进行初始化。

答案 4 :(得分:0)

这是由于CLR处理结构和类的方式不同。结构是值类型,这意味着它们位于堆栈而不是托管堆中。保持结构很小是一个很好的经验法则,因为一旦你开始将它们作为方法参数传递,你将会产生开销,因为结构在传递给方法时会被完整地复制。

由于类传递了对方法的引用副本,因此当用作方法参数时,它们会产生更少的开销。

确定类大小的最佳方法是总计所有类成员所需的字节数加上CLR开销的额外8个字节(同步块索引和对类型的引用)宾语)。

答案 5 :(得分:0)

结构与类不同,因为它们存储在堆栈中,而不是存储在堆上。这意味着每次使用struct作为参数调用方法时,都会创建一个副本并将其传递给该方法。这就是大结构非常低效的原因。

我会积极地阻止使用结构,因为它可能会导致一些微妙的错误:例如当你更改一个结构的一个字段时,它不会反映给调用者(因为你只更改了副本) - 这与类完全不同。

因此,我认为16个字节是一个合理的结构最大大小,但在大多数情况下,最好有一个类。如果您仍想创建结构,请尝试至少使其成为不可变的。

答案 6 :(得分:0)

复制结构实例比创建类的新实例和从旧实例复制数据花费的时间更少,但是类实例可以共享而结构实例则不能。因此,“structvar1 = structvar2”需要复制新的struct实例,而“classvar1 = classvar2”允许classvar1和classvar2引用相同的struct实例(无需创建新的实例)。

处理新结构实例创建的代码针对最大16字节的大小进行了优化。较大的结构处理效率较低。如果每个包含结构的变量都包含一个独立的实例(即没有理由认为任何特定的两个变量将保存相同的实例),结构就是胜利;在许多变量可以保持相同实例的情况下,它们并不是一场胜利(如果它们是一场胜利)。