关于结构的问题

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

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

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

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

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

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

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

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

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

是什么限制了结构体像一个类一样?

有很多不同之处。 例如,您不能从结构inheritance。

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

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

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

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

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

我会主动阻止使用结构,因为它可能会导致一些微妙的错误:例如,当您更改结构的字段时,它不会反映给调用者(因为您只更改了副本) – 这是完全不同的行为上课。

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

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

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

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

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