什么时候应该在C#中使用结构而不是类?我的概念模型是,当项只是值类型的集合时,使用结构。一种将它们逻辑地结合在一起的方法。
我在这里遇到了这些规则:
结构应表示单个价值结构应具有内存占用空间小于16字节。结构不应在之后更改创造
这些规则有效吗?结构在语义上意味着什么?
什么时候应该在C#中使用结构而不是类?我的概念模型是,当项只是值类型的集合时,使用结构。一种将它们逻辑地结合在一起的方法。
我在这里遇到了这些规则:
结构应表示单个价值结构应具有内存占用空间小于16字节。结构不应在之后更改创造
这些规则有效吗?结构在语义上意味着什么?
当前回答
结构是值类型。如果将结构分配给新变量,则新变量将包含原始变量的副本。
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
其他回答
C#结构是类的轻量级替代。它可以做的几乎与类相同,但使用结构而不是类的“成本”更低。这样做的原因有点技术性,但总而言之,类的新实例放在堆上,新实例化的结构放在堆栈上。此外,您不是像处理类那样处理对结构的引用,而是直接处理结构实例。这也意味着,当您将结构传递给函数时,它是按值传递的,而不是作为引用。在关于函数参数的章节中有更多关于这一点的内容。
因此,当您希望表示更简单的数据结构时,尤其是如果您知道要实例化大量数据结构,那么应该使用结构。在.NET框架中有很多示例,其中Microsoft使用了结构而不是类,例如Point、Rectangle和Color结构。
类最适合将复杂的操作和数据分组在一起这将在整个项目中发生变化;结构是更好的选择大多数情况下保持不变的简单对象和数据。除了它们的用途之外,它们在一个键上有根本的不同即变量之间传递或分配的方式。类是引用类型,这意味着它们由参考结构是值类型,这意味着它们是由价值
小心使用类。如果您有一些引用相同内存的游戏对象,修改其中一个将修改其他对象。
创建结构对象时,其所有数据都存储在没有引用或连接到其内存的对应变量地方这使得结构对于创建需要快速高效地复制,同时保留独立的身份。
ExampleStruct struct1= new ExampleStruct()
ExampleStruct struct2= struct1
修改结构2不会影响结构1。
基本上,创建结构是为了提高性能。但是,由于涉及到所有的复制,有时结构可能会更慢。如果结构有很多需要复制的变量,那么将其转换为类并传递引用可能会更快如果您有一个结构数组,那么数组本身就是堆上的一个对象,结构值包含在数组中。所以垃圾收集器只有一个对象需要考虑。如果数组超出范围,垃圾收集器可以在一个步骤中释放数组中的所有结构。如果代码的任何其他部分正在使用此数组中的结构,由于结构被复制,因此我们可以安全地释放数组本身及其内容。如果您有一个对象数组,那么数组本身和数组中的每个对象都是堆上的独立对象。每个对象都可以存储在堆的完全不同的部分,而代码的另一部分可能会引用这些对象。因此,当我们的数组超出范围时,我们无法立即释放数组。因为垃圾收集器必须单独考虑每个对象,并确保在取消分配之前没有对每个对象的引用。
我认为一个好的第一近似值是“从不”。
我认为一个好的二次近似是“从不”。
如果你渴望表现,那么考虑一下,但始终要衡量。
结构是值类型。如果将结构分配给新变量,则新变量将包含原始变量的副本。
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
不,我不完全同意这些规则。它们是考虑性能和标准化的良好指南,但不是根据可能性。
正如你在回答中看到的,有很多创造性的方法来使用它们。因此,这些指导原则需要做到这一点,始终是为了性能和效率。
在本例中,我使用类以更大的形式表示真实世界的对象,使用结构来表示具有更精确用途的较小对象。你说的是,“一个更具凝聚力的整体”。类将是更多面向对象的元素,而结构可以具有这些特性,尽管规模较小。IMO。
我在Treeview和Listview标签中经常使用它们,在这些标签中可以非常快速地访问常见的静态属性。我一直在努力以另一种方式获取这些信息。例如,在我的数据库应用程序中,我使用Treeview,其中包含表、SP、函数或任何其他对象。我创建并填充我的结构,将其放入标记中,将其拉出,获取所选内容的数据等等。我不会在课堂上这样做!
我确实会尽量缩小它们,在单实例情况下使用它们,并防止它们发生变化。注意内存、分配和性能是明智的。测试是非常必要的。