什么时候应该在C#中使用结构而不是类?我的概念模型是,当项只是值类型的集合时,使用结构。一种将它们逻辑地结合在一起的方法。
我在这里遇到了这些规则:
结构应表示单个价值结构应具有内存占用空间小于16字节。结构不应在之后更改创造
这些规则有效吗?结构在语义上意味着什么?
什么时候应该在C#中使用结构而不是类?我的概念模型是,当项只是值类型的集合时,使用结构。一种将它们逻辑地结合在一起的方法。
我在这里遇到了这些规则:
结构应表示单个价值结构应具有内存占用空间小于16字节。结构不应在之后更改创造
这些规则有效吗?结构在语义上意味着什么?
当前回答
无论何时:
不需要多态性,want值语义,以及希望避免堆分配和相关的垃圾收集开销。
然而,需要注意的是,结构(任意大)传递比类引用(通常是一个机器字)更昂贵,因此类在实践中可能会更快。
其他回答
以下是在Microsoft网站上定义的规则:
✔️ 如果类型的实例很小且通常很短,或者通常嵌入在其他对象中,请考虑定义结构而不是类。
❌ 避免定义结构,除非该类型具有以下所有特征:
它在逻辑上表示单个值,类似于原始类型(int、double等)。
它的实例大小小于16字节。
它是不可变的。
它不必经常装箱。
供进一步阅读
我很少对事物使用结构。但这只是我,这取决于我是否需要对象为空。
如其他答案所述,我对真实世界的对象使用类。我也有结构用于存储少量数据的想法。
C#结构是类的轻量级替代。它可以做的几乎与类相同,但使用结构而不是类的“成本”更低。这样做的原因有点技术性,但总而言之,类的新实例放在堆上,新实例化的结构放在堆栈上。此外,您不是像处理类那样处理对结构的引用,而是直接处理结构实例。这也意味着,当您将结构传递给函数时,它是按值传递的,而不是作为引用。在关于函数参数的章节中有更多关于这一点的内容。
因此,当您希望表示更简单的数据结构时,尤其是如果您知道要实例化大量数据结构,那么应该使用结构。在.NET框架中有很多示例,其中Microsoft使用了结构而不是类,例如Point、Rectangle和Color结构。
我使用结构来打包或解包任何类型的二进制通信格式。这包括读取或写入磁盘、DirectX顶点列表、网络协议或处理加密/压缩数据。
在这方面,你列出的三条准则对我来说并不有用。当我需要以特殊顺序写出400字节的内容时,我将定义一个400字节的结构,并用它应该具有的任何不相关的值填充它,我将以当时最合理的方式设置它。(好吧,四百字节会很奇怪——但当我以写Excel文件为生的时候,我处理的是多达四十字节的结构,因为这就是一些BIFF记录的大小。)
结构是值类型。如果将结构分配给新变量,则新变量将包含原始变量的副本。
public struct IntStruct {
public int Value {get; set;}
}
执行以下操作将导致存储在内存中的结构的5个实例:
var struct1 = new IntStruct() { Value = 0 }; // original
var struct2 = struct1; // A copy is made
var struct3 = struct2; // A copy is made
var struct4 = struct3; // A copy is made
var struct5 = struct4; // A copy is made
// NOTE: A "copy" will occur when you pass a struct into a method parameter.
// To avoid the "copy", use the ref keyword.
// Although structs are designed to use less system resources
// than classes. If used incorrectly, they could use significantly more.
类是引用类型。将类分配给新变量时,该变量包含对原始类对象的引用。
public class IntClass {
public int Value {get; set;}
}
执行以下操作只会导致内存中类对象的一个实例。
var class1 = new IntClass() { Value = 0 };
var class2 = class1; // A reference is made to class1
var class3 = class2; // A reference is made to class1
var class4 = class3; // A reference is made to class1
var class5 = class4; // A reference is made to class1
结构可能会增加代码错误的可能性。如果将值对象视为可变引用对象,那么当所做的更改意外丢失时,开发人员可能会感到惊讶。
var struct1 = new IntStruct() { Value = 0 };
var struct2 = struct1;
struct2.Value = 1;
// At this point, a developer may be surprised when
// struct1.Value is 0 and not 1