2

Microsoft 对使用 struct 有以下规则:

如果类型的实例很小且通常短暂存在或通常嵌入在其他对象中,请考虑定义结构而不是类。

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

  1. 它在逻辑上表示单个值,类似于原始类型(整数、双精度等)。
  2. 它的实例大小小于 16 字节。
  3. 它是不可变的。
  4. 它不必经常装箱。

据我了解,当你想要一个值类型的行为时,你会创建 struct 。当然,这会在分配并将其传递给函数时给您带来复制开销。但是你为什么要遵循#2 和#3 呢?如果您的值类型太大怎么办?此外,我不明白您为什么要将不可变类型设为值类型。如果类型是不可变的,则最好节省通过引用传递它的时间,因为无论如何它都无法更改。

我问的原因是我正在制作一个游戏,其中对象具有 Vector2d 类型的坐标、速度等属性。问题是,我应该制作 Vector2d 不可变结构(这不会需要大量额外的内存吗?)、可变结构(人们说它们是邪恶的)还是只是类(我必须总是调用 vector.Clone() 否则我可能无意中得到两个具有相同向量变量的对象)

4

4 回答 4

2

此外,我不明白您为什么要将不可变类型设为值类型。

int类型是不可变类型,是您需要不可变值类型的完美示例。

想象一下,如果int是引用类型。如果每次使用整数时都必须取消引用,那将非常昂贵。实际上,当您使用“装箱”整数(例如,存储在类型变量中的整数)时,就会发生这种情况object。与 Java 相比,.NET 的一项改进是集合可以保存未装箱的整数。

如果类型是不可变的,您最好节省通过引用传递它的时间

是的,如果它很大且不可变,那么您可以通过引用传递它来节省时间。这就是为什么指南建议大类型应该是引用类型。

于 2012-12-22T22:24:00.550 回答
1

16 字节似乎有些随意,但可能与典型 CPU 的高速缓存行大小有关。这比现代 CPU 上的 64 字节高速缓存行小得多。可能是因为你不能明确地将你的结构对齐到一行。

让你再次输入不可变避免了通过引用传递的需要。相反,只需返回一个新实例。跟随引用比使用缓存值要昂贵得多,保持对象小会增加它保留在缓存中的机会。

一般来说,如果您想要引用语义,请将其设为类,否则将其设为结构。我建议您遵循 MS 指南,除非您可以证明使用分析器(或其他一些经验证据)有充分的理由不这样做。

于 2012-12-22T22:28:28.630 回答
0

对于#2,不应轻易复制大型结构,因此大多数时候应该是一个类。此外,这些不是硬性规则,只是经验法则。如果您有充分的理由不遵守规则,请继续。

于 2012-12-22T22:21:11.390 回答
-1
  1. 当传递/操作一个结构时,它的整个值必须在堆栈周围复制,而不仅仅是一个引用。一旦它达到一定的大小,16 字节,考虑只使用一个类来避免开销。

  2. 不变性更像是一种旨在减少代码错误的模式,而不是硬性规定。如果您的值类型可能是不可变的,那么这样做会很有帮助。

你可能误解了不变性。您的变量可以更改值,但值本身不会更改。例如,您可以拥有一个 Datetime 变量并将其设置为任何其他 DateTime 实例,但在实例初始化后您实际上无法更改该实例的字段。

于 2012-12-22T22:25:59.053 回答