C#,结构体 vs 类,哪个更快?

22

可能重复的问题:
哪种数据存储方式最好:Struct或Classes?

假设我有一个Employee对象,具有像年龄、姓名、性别、职称和薪资等属性。现在我有一个列表,想用一些Employee来填充它(每个Employee实例都是唯一的)。

就速度和内存占用而言,在上述场景中创建Employee时,使用Struct还是Class更可取?

欢迎提供有关上述场景中Struct和Class的任何其他注意事项。


2
@Jon:你的副本是针对C ++而不是C#的。它们有所不同。 - Joe
2
结构体和类具有非常不同的属性。如果你基于速度来选择,你很快就会陷入麻烦。 - H H
2
没关系,你甚至懒得稍微改变一下问题...直接复制了2007年的问题。请参考马特的答案。 - H H
1
请仅返回翻译后的文本:来源:http://discuss.joelonsoftware.com/default.asp?dotnet.12.489354.15 - H H
我简直不敢相信人们会在这里发布其他网站上的重复问题来建立声誉。 - Gavin Williams
显示剩余2条评论
3个回答

44

结构体仅适用于应具有类似值类型行为的相对较小的结构。

除非该类型具备以下所有特征,否则不要定义结构体:

  • 它在逻辑上代表单个值,类似于原始类型(整数、双精度等)。
  • 它的实例大小小于16字节。
  • 它是不可变的。
  • 它不需要经常装箱。

您的类型违反了前两个指南,可能也违反了第三个指南。因此,在此处绝对应使用类。


6
这句话的意思是“它不需要经常装箱”。 - alex
7
基本上,这意味着将结构体强制转换为一个类型,这将导致它在堆上分配内存。(将结构体作为值强制转换为指向对象或任何由结构体实现的接口的指针类型) - wingerse
1
你如何确定一个实例的大小? - Antarr Byrd
@AntarrByrd 不错的问题。我认为获取一个想法的一种非常可靠的方式就是确定字段的大小。例如,如果“int”类型占4个字节,那么假设您结构体中的所有字段都将是“int”,那么该结构体应该最多有4个(“int”)字段(4个字段* 4个字节= 16个字节)。 - CosmicGiant
1
这完全没有回答问题。问题是关于“速度和内存占用”,而不是最佳编码实践。 - FINDarkside
显示剩余2条评论

15

这并不是那么简单-你需要描述行为。例如,一个结构体可以随时复制自己,因此在某些方面它们可能会消耗更多的内存。但是,作为原始数据转储的结构体数组可以避免(非常小的)对象头(和额外的解引用),因此可以提高效率。

然而,一个更大的问题在于你如何概念化它们;雇员不是一个值;如果我赋值:

var emp = GetEmployee();
var tmp = emp;

这是否意味着我现在应该有2名员工?很可能不是这样。那如果我改变:

tmp.Name = "Fred";

这是否会影响emp取决于它是结构体还是类。我认为这里应该是类。我还建议一个结构体应该几乎总是 是不可变的,以避免这种数据丢失的情况。虽然有可变结构体的情况,但由于经常被错误使用,我不想无意中鼓励你这样做。

结构体的封装也存在其他问题;考虑员工是否有经理;这是可能的吗?

[struct|class] Manager {
    private Manager boss;
}

这仅适用于类。再次强调:结构体不太适合这种类型的用法。也不适用于多态、抽象等。


从概念上讲,我认为在许多方面,值类型语义比结构语义更清晰。给定一个类似于矩形的结构体数组,"ArrayOfRect[3].Width = 34;" 的效果是明确的,因为根据定义,数组的每个元素都引用不同的 Rectangle 实例。假设有一个某种类似于矩形的类的数组,并希望使元素 3 具有与现在相同的属性,但宽度为 34。该如何处理? - supercat
@supercat,您的评论不太清楚,因为value-type === struct(您对这两个进行了对比);此外,可变结构体(ArrayOfRect [3] .Width = 34;)几乎总是一个非常糟糕的想法,并导致出现微妙问题的情况。关于最后一个问题...呃,与您的示例完全相同,只是使用类,这样做并不是一件坏事。 - Marc Gravell
1
我原以为我在对比结构体和类,并指出结构体语义上的数组比类更清晰。Lippert先生真的很讨厌可变结构体,因为.NET处理它们的方式存在一些怪癖和限制,但它们并不是“非常糟糕的想法”。除了一些(通常是人为的)罕见异常情况外,可变结构体的所有语义上有趣的状态都由其字段的内容定义。相比之下,对象的状态往往在很大程度上取决于存在哪些对它的引用 - supercat
在我看来,“普通的数据结构”已经是一个错误的称呼了。结构体最好保留给,而不是对象。 - Marc Gravell
@supercat 我认为我们在根本上存在分歧;不过,无论你用什么方法都可以。 - Marc Gravell
显示剩余2条评论

4
那取决于情况,也许在这种情况下使用类会更好。希望以下几点能帮助您做出决定。 在以下情况下使用结构体是可取的。 当您有小型数据结构时
数据结构不需要扩展功能。
当您想在数据结构上执行更快的操作时。(由于结构体存储在堆栈上,在其上执行的操作更快。) 在以下情况下使用类是可取的。 当您拥有复杂的数据结构时
数据结构需要扩展功能。
当您想优化内存使用时。(由于类存储在堆中,当没有指向对象的引用时,它们将被垃圾回收。)
查看此处以获取更多详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接