Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么.NET结构应该小于16字节?_C#_.net - Fatal编程技术网

C# 为什么.NET结构应该小于16字节?

C# 为什么.NET结构应该小于16字节?,c#,.net,C#,.net,我已经在一些地方读到,结构的最大实例大小应该是16字节 但我看不出这个数字(16)是从哪里来的 在网上浏览,我发现一些人认为这是一个性能良好的近似数字,但微软认为这是一个很难达到的上限。(例如) 有人对为什么是16字节有明确的答案吗?我认为从性能的角度来看,16字节只是一条经验法则。NET中的对象使用至少24字节的内存(IIRC),因此,如果您将结构设置为比这大得多,则引用类型更可取 我想不出他们为什么特别选择16字节的原因。大小数字主要来自于在堆栈上复制结构所需的时间,例如传递给方法所需的时间

我已经在一些地方读到,结构的最大实例大小应该是16字节

但我看不出这个数字(16)是从哪里来的

在网上浏览,我发现一些人认为这是一个性能良好的近似数字,但微软认为这是一个很难达到的上限。(例如)


有人对为什么是16字节有明确的答案吗?

我认为从性能的角度来看,16字节只是一条经验法则。NET中的对象使用至少24字节的内存(IIRC),因此,如果您将结构设置为比这大得多,则引用类型更可取


我想不出他们为什么特别选择16字节的原因。

大小数字主要来自于在堆栈上复制结构所需的时间,例如传递给方法所需的时间。任何比这个大得多的东西,只要复制数据就会消耗大量的堆栈空间和CPU周期,而对不可变类的引用(即使是取消引用)可能会更有效率。

这只是一个性能经验法则

关键是,由于值类型是按值传递的,因此如果将结构传递给函数,则必须复制结构的整个大小,而对于引用类型,则只需复制引用(4字节)。结构可能会节省一些时间,因为您删除了一层间接寻址,所以即使它大于这4个字节,也可能比传递引用更有效。但在某些时候,它变得如此巨大,以至于复制的成本变得显而易见。通常的经验法则是,这通常发生在16字节左右。选择16是因为它是一个很好的整数,是2的幂,备选值要么是8(这太小了,会使结构几乎无用),要么是32(在这一点上,如果出于性能原因使用结构,复制结构的成本已经成问题)

但归根结底,这是性能建议。它回答了“使用结构还是类,哪一种最有效?”。但它并没有回答“哪一个最好地映射到我的问题域”的问题

结构和类的行为不同。如果你需要一个结构的行为,那么我会说让它成为一个结构,无论大小。至少在您遇到性能问题之前,请分析您的代码,并发现您的结构存在问题

你的链接甚至说这只是性能问题:

如果这些条件中的一个或多个是 未满足,请创建引用类型 而不是一个结构。未能 坚持这一方针可以 对绩效产生负面影响


如果一个结构不大于16字节,可以用几个简单的处理器指令来复制它。如果较大,则使用循环复制结构


只要结构不大于16字节,处理器在复制结构时所做的工作与复制引用时所做的工作大致相同。如果结构更大,您将失去拥有结构所带来的性能优势,通常应将其改为类。

以下是一种结构可以表现出优异性能的场景:

当您需要创建1000个实例时。在本例中,如果要使用类,首先需要分配数组以容纳1000个实例,然后在循环中分配每个实例。但是,如果要使用structs,那么在分配将容纳1000个实例的数组后,这些实例将立即可用

此外,当您需要进行互操作或出于性能原因需要深入研究不安全的代码时,结构非常有用

就像往常一样,有一个权衡,我们需要分析他们在做什么,以确定实现某件事情的最佳方式


ps:当我使用激光雷达数据时,这个场景开始发挥作用,其中可能有数百万个点代表地面数据的x、y、z和其他属性。这些数据需要加载到内存中,以便进行密集的计算以输出各种内容。

正如其他答案所指出的那样,复制大于某个阈值的结构所需的每字节成本(在早期版本的.NET中为16字节,但后来增长到20-24字节)远远大于较小结构的每字节成本。但是,需要注意的是,复制任何特定大小的结构一次只需创建相同大小的新类对象实例的成本的一小部分。如果一个结构在其生命周期内会被多次复制,并且不特别需要值类型语义,那么类对象可能更可取。但是,如果一个结构最终只被复制一到两次,那么这种复制可能比创建一个新的类对象便宜。类对象变得更便宜的盈亏平衡拷贝数随所讨论的结构/对象的大小而变化,但低于“便宜拷贝”阈值的拷贝数要比高于该阈值的拷贝数高得多


顺便说一句,另一点值得一提的是,将结构作为
ref
参数传递的成本与结构的大小无关。在许多情况下,可以通过使用值类型并通过
ref
传递它们来实现最佳性能。Once必须小心避免使用结构类型的属性或
readonly
字段,因为访问其中任何一个都会创建相关结构的隐式临时副本。

是的,链接确实说这是性能问题,但它使用的语言也很强,即“不要定义结构…”。他们本可以说“这是不可取的……”的确,措辞似乎有点强硬。但可能需要强调的是,堆分配的类并不慢(正如来自C/C++的程序员所期望的那样),精确数字的一个可能答案是16字节的stru