什么时候应该使用结构而不是类?
MSDN说,当我们需要轻量级对象时,应该使用结构。在某个结构比一类更可取的情况下,还有其他情况吗?
有些人可能已经忘记了:
- 结构可以有方法。
- 结构不能被继承。
我了解结构和类之间的技术差异,只是我对何时使用结构感觉不太好。
解决方案
回答
当我们需要值类型语义而不是引用类型语义时,请使用结构。结构是按值复制的,所以要小心!
另请参阅先前的问题,例如
.NET中的struct和class有什么区别?
回答
当我们实际上不需要行为,但需要的结构比简单的数组或者字典更多时。
跟进
这就是我总体上对结构的看法。我知道他们可以有方法,但是我喜欢保持整体的精神差异。
回答
正如@Simon所说,结构提供"值类型"语义,因此,如果我们需要与内置数据类型相似的行为,请使用结构。由于结构是通过副本传递的,因此我们要确保它们的大小很小,大约16个字节。
回答
在以下情况下,我将使用结构:
- 一个对象应该是只读的(每次我们传递/分配一个结构时,它都会被复制)。对于多线程处理,只读对象非常有用,因为在大多数情况下,它们不要求退出锁定。
- 一个物体很小,寿命短。在这种情况下,很有可能将对象分配到堆栈上,这比将其放在托管堆上的效率要高得多。而且,对象超出其范围后,将立即释放该对象分配的内存。换句话说,对于垃圾收集器,它的工作量更少,并且内存使用效率更高。
回答
MSDN有答案:
在类和结构之间进行选择。
基本上,该页面为我们提供了4个项目的清单,并说要使用一个类,除非类型符合所有条件。
Do not define a structure unless the type has all of the following characteristics: It logically represents a single value, similar to primitive types (integer, double, and so on). It has an instance size smaller than 16 bytes. It is immutable. It will not have to be boxed frequently.
回答
当我想将一些值组合在一起以将方法调用中的内容传递回去时,我一直使用结构,但是在读取这些值之后,就不需要将其用于任何东西。只是保持物品清洁的一种方式。我倾向于将结构中的事物视为"可丢弃",而将类中的事物视为更为有用和"实用"
回答
唔...
我不会使用垃圾回收作为/反对使用struct vs类的参数。托管堆的工作原理类似于堆栈,创建对象只是将其放在堆的顶部,这几乎与在堆栈上分配的速度一样快。此外,如果对象是短暂的,并且无法在GC周期中幸免,则释放是免费的,因为GC仅适用于仍可访问的内存。 (搜索MSDN,有一系列有关.NET内存管理的文章,我太懒了以至于无法对其进行深入研究)。
在大多数情况下,我使用struct时都会发狂,因为后来我发现拥有引用语义会使事情变得简单一些。
无论如何,上面发布的MSDN文章中的那四点似乎是一个很好的准则。
回答
令我惊讶的是,我没有阅读任何先前的答案,我认为这是最关键的方面:
我想要没有身份的类型时使用结构。例如3D点:
public struct ThreeDimensionalPoint { public readonly int X, Y, Z; public ThreeDimensionalPoint(int x, int y, int z) { this.X = x; this.Y = y; this.Z = z; } public override string ToString() { return "(X=" + this.X + ", Y=" + this.Y + ", Z=" + this.Z + ")"; } public override int GetHashCode() { return (this.X + 2) ^ (this.Y + 2) ^ (this.Z + 2); } public override bool Equals(object obj) { if (!(obj is ThreeDimensionalPoint)) return false; ThreeDimensionalPoint other = (ThreeDimensionalPoint)obj; return this == other; } public static bool operator ==(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2) { return p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z; } public static bool operator !=(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2) { return !(p1 == p2); } }
如果我们有此结构的两个实例,则不必关心它们是内存中的单个数据还是两个。我们只关心它们所拥有的价值。