C# 关于结构的问题

C# 关于结构的问题,c#,class,struct,language-specifications,C#,Class,Struct,Language Specifications,MSDN表示16字节或更少的类最好作为结构处理。 为什么会这样? 这是否意味着如果一个结构超过16个字节,它的效率会低于一个类,或者是相同的? 如何确定类是否小于16字节? 什么限制结构像类一样工作?(除了不允许无参数构造函数)在内存中,结构将直接保存数据,而类的行为更像指针。这本身就是一个重要的区别,因为将结构作为参数传递给方法将传递其值(在堆栈上复制它们),而类将传递对值的引用。如果结构很大,那么每次方法调用都会复制很多值。当它真的很小时,复制值并直接使用它们可能比复制指针并从另一个地方获取

MSDN表示16字节或更少的类最好作为结构处理。
为什么会这样?
这是否意味着如果一个结构超过16个字节,它的效率会低于一个类,或者是相同的?
如何确定类是否小于16字节?

什么限制结构像类一样工作?(除了不允许无参数构造函数)

在内存中,结构将直接保存数据,而类的行为更像指针。这本身就是一个重要的区别,因为将结构作为参数传递给方法将传递其值(在堆栈上复制它们),而类将传递对值的引用。如果结构很大,那么每次方法调用都会复制很多值。当它真的很小时,复制值并直接使用它们可能比复制指针并从另一个地方获取它们要快


关于限制:您不能将其分配给null(尽管您可以使用Nullable),您必须立即初始化它。

检查此链接,我在SO today中的一个答案中找到了它:。您还可以尝试搜索SO并通过谷歌搜索“引用类型vs值类型”来查找结构和类之间的差异

什么限制结构像类一样工作

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


不能有虚拟方法,因此不能使用结构实现接口。结构中的实例方法可以访问结构的私有字段,但除此之外,它们的行为非常类似于辅助“helper”函数(对于不可变结构,它们有时甚至不需要访问私有数据)。因此,我发现它们不如类方法那么“有价值”。

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

  • struct
    s是值类型,
    class
    es是引用类型。如果总存储量使用16个字节,那么为每个字节创建内存引用(4到8个字节)可能不值得
  • 当您拥有非常小的对象时,通常可以将它们推送到IL堆栈上,而不是对对象的引用。这确实可以加快一些代码的速度,因为您消除了被调用方端的内存取消引用
  • IL中的类有一些额外的“绒毛”,如果您的数据结构非常小,那么这些绒毛都不会被使用,所以它只是您不需要的额外垃圾

然而,
struct
class
之间最重要的区别在于,
struct
s是值类型,
class
es是引用类型。

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

由于类将其引用的副本传递给方法,因此当用作方法参数时,它们产生的开销要小得多


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

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

尽管如此,我还是不鼓励使用
struct
s,因为它可能会导致一些微妙的错误:例如,当您更改
struct
的字段时,它不会反映给调用方(因为您只更改了副本),这与类的行为完全不同

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

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

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

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


当然,真正的答案是使用在你的情况下最有效的方法。在大多数情况下,使用类会更好。

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

处理新结构实例创建的代码针对最大16字节的大小进行了优化。较大的结构处理效率较低。如果持有结构的每个变量将持有一个独立实例(即,没有理由期望任何特定的两个变量将持有相同的实例),则结构是一种胜利;在某些情况下,他们并不算是一场胜利(如果他们真的是一场胜利的话)