C#中Class vs Structure的“开销”?

时间:2010-05-03 22:53:38

标签: c# class struct

我正在做课程3354(在.NET Framework 2.0中实现系统类型和接口),据说对于简单的类,使用成员变量和函数,最好使用结构而不是类,因为开销

我从未听说过这样的事情,这种说法的有效性是什么?

11 个答案:

答案 0 :(得分:12)

我建议从不使用结构,除非你有一个非常具体的用例,并且确切知道结构将如何使系统受益

虽然C#结构确实允许成员,但它们的工作方式与类不同(不能是子类型,没有虚拟调度,可能完全存在于堆栈中)并且行为会根据提升而改变等等(提升是将价值类型推广到堆中的过程 - 出乎意料!)

所以,回答这个问题:我认为C#中最大的误解之一就是使用结构“来表现”。造成这种情况的原因是“开销”无法真正衡量,如果没有看到它与系统的其他部分如何相互作用以及角色,如果有任何值得注意的话,它就会起作用。这需要进行分析,不能用“减少开销”等简单的陈述来概括。

结构值类型有一些好的个案 - 一个例子是存储在图像数组中的复合RGB值。这是因为RGB类型很小,图像中可以有很多非常,数值类型可以很好地打包在数组中,并且可以帮助保持更好的内存局部性等。

答案 1 :(得分:9)

出于性能原因,您通常不应将应该是类的类型更改为结构。结构和类具有不同的语义,并且不完全可互换。确实,结构有时可以更快,但它们有时也可能更慢。它们的行为不同,您应该知道何时使用其中一种。

MSDN在choosing between classes and structures上有一个页面。

摘要是:

  

除非是,否则不要定义结构   type具有以下所有内容   特性:

     
      
  • 它逻辑上表示单个值,类似于原始类型   (整数,双精度等)。
  •   
  • 实例大小小于16个字节。
  •   
  • 这是不可改变的。
  •   
  • 不必频繁装箱。
  •   

有时可能会出现类型确实应该是类的情况,但出于性能原因,您需要将其作为结构。这很少见,你应该确保在走这条路线之前知道自己在做什么。如果你打破结构的不变性指南,那么这可能会特别危险。可变结构的行为方式可能是大多数程序员不期望的。

答案 2 :(得分:8)

当C#处于测试阶段时,我接受了对类和结构之间差异的演示。开发人员已经构建了一个Mandelbrot集查看器,它可以研究很多复杂的数字来完成它的结果。在第一个例子中,他们运行代码,复杂的数字表示为具有Real和Imaginary字段的类。然后,他们将单词class更改为struct并重新编译。性能差异很大。

在这种情况下,不必分配堆对象也不必对其进行垃圾收集,这就是产生差异的原因。根据您拥有的物体数量,差异可能或多或少都很大。在开始调整之前,请测量您的表现,然后再决定是否使用值类型。

答案 3 :(得分:2)

你将在95%的时间内使用课程。价值类型语义最终会让你陷入困境,而不是在路上。

但是,如果你要使用结构,请确保它是不可变的。

答案 4 :(得分:1)

在C#中,类和结构是完全不同的野兽。两者的语法几乎相同,但行为完全不同(引用与值)。结构的单个实例将使用比等效类更少的内存,但是一旦开始构建集合或传递它们,值类型语义将在性能方面(以及可能的内存消耗取决于您正在做的事情)杀死您,除非结构中的数据非常小。我不知道硬数是多少,但我们谈的是8字节或更少的数量级。

它在可维护性和可读性方面也会受到影响,因为这两者看起来很相似,但行为却截然不同。

答案 5 :(得分:1)

你可以遵循的一条经验法则是问自己你要做的事情是System.Date 如果不是,那么你真的应该质疑你的决定使用结构。

答案 6 :(得分:0)

struct是值类型,类是引用类。这可能是其中一个原因。

答案 7 :(得分:0)

对于你将拥有其中许多类型的简单类型,不需要继承,并且是不可变的良好候选者,结构是一个不错的选择。例如,Point,Rectangle,Decimal和DateTime。

如果你不会有很多,那么开销是无关紧要的,它不应该影响你的决定。如果你需要从它派生(或使它成为派生类型),它必须是一个类。如果该项不能是不可变的,那么struct不是一个好的候选者,因为改变一个实例不会改变它的任何副本。

答案 8 :(得分:0)

我认为最常引用的收支平衡点是结构中大约12个字节的数据。例如,3个整数。值类型和引用类型之间的区别更为重要,您应该根据成员很少的类型做出选择。

如果事情很重要,那么上课:)

答案 9 :(得分:0)

结构是值类型,类是引用类型。因此,如果您要传递引用,那么类可以在性能方面更好,因为您复制的是地址而不是整个结构。但是,如果要多次实例化和引用这些对象,结构将更好地执行,因为它们是在堆栈上分配的。因此,对于性能很重要的众多对象或需要值类型语义的小对象,结构可能更好。结构也没有默认构造函数。它们继承自Object,但除此之外它们都是无继承的。

答案 10 :(得分:-1)

无需分配/解除分配结构。