不可变类与不可变结构

发布于 2024-11-29 19:59:39 字数 212 浏览 1 评论 0原文

我有一个类,它一开始是可变的,但后来我让它变得不可变。我应该将其更改为struct吗?选择其中之一时会考虑哪些因素?我的具体情况是一个 Point 类型类(它表示自定义坐标系中的坐标),它由 4 个 int 字段以及一些用于访问相同字段的属性组成数据以不同的方式。我注意到 String 是一个类并且是不可变的,因此必须有一些用例。

I have a class that started life being mutable, but I've since made it immutable. Should I change it to be a struct? What sort of considerations go into choosing one over the other? My particular case is a Point type class (it represents a coordinate in a custom coordinate system) that is made up of 4 int fields, plus a few properties to access the same data in different ways. I note that String is a class and is immutable, so there must be some use-case for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

月光色 2024-12-06 19:59:39

一般来说,不,您不应该将其更改为结构体。仅仅因为它是不可变的并不意味着它自动成为结构体的良好候选者。

结构应该很小。对于四个整数,它正好达到建议的 16 字节限制,此时结构的性能开始下降。

结构应该代表某种类型的单个实体。也许你的班级会这样做,但从你的描述来看,这听起来不太可能。

结构比类更难正确实现。它应该对比较之类的事情表现良好,因此需要实现的东西比类的预期要多。

除非您有充分的理由将其实现为结构体,例如性能问题,否则您应该将您的类保留为一个类。

Generally, no, you should not change it to a struct. Just because it's immutable doesn't mean that it's automatically a good candidate for being a struct.

A struct should be small. With your four ints it's just at the recommended limit of 16 bytes where performance for structs starts to degrade.

A struct should represent a single entity of some kind. Perhaps your class does that, but from your description it doesn't sound likely.

A structure is harder to implement correctly than a class. It should behave well to things like comparisons, so there are more things to implement than what is expected of a class.

Unless you have a really good reason to implement it as a struct, like performance issues, you should keep your class as a class.

琉璃梦幻 2024-12-06 19:59:39

据我了解,使用结构而不是类是一个优化问题。结构体存储在堆栈上而不是堆上,因此它们非常适合作为大量使用的多个字段的轻量级捆绑。每当在方法之间传递时,它们都会被复制,这使得传递它们的成本更高——但这可能会满足您对不变性的渴望。使用结构的缺点包括语言施加的自然限制。

我根本不是这个主题的专家,但想提出这个方面。经验丰富的人当然应该介入并扩展这一点。另外,这里有一个有用的讨论:何时使用 struct?

最终我想说,如果不变性是您唯一的考虑因素,请将其保留为一类(特别是现在我看到其他人表达了这一观点)。无论是否是结构体,都可以实现不变性,因此这件事似乎没有很强的相关性。

As I understand, using a struct instead of a class is a matter of optimization. Structs are stored on the stack rather than the heap, so they are well suited as lightweight bundles of multiple fields that are used in great quantity. They are copied whenever passed between methods, which makes passing them more expensive - however this may lend itself to your desire for immutability. Disadvantages of using structs include the natural restrictions imposed by the language.

I'm not at all an expert on the subject but wanted to bring this aspect up. Someone with more experience should certainly step in and expand on this. Also, here is a useful discussion on it: When to use struct?

Ultimately I would say if immutability is your only consideration, keep it a class (especially now that I see others voicing this opinion). Immutability can be achieved regardless of being a struct, so the matter doesn't seem strongly related.

老娘不死你永远是小三 2024-12-06 19:59:39

如果它很小并且不可变,那么将其设为结构体会更好。特别是如果您要收集大量积分。如果您有一个包含 100 万个 Point 的列表,那么就 GC 时间和每个对象实例 16 字节的额外开销而言,所有这些对象都会产生大量开销。

字符串必须是引用类型,因为您不能也不想在堆栈上存储可变数量的字符,更不用说实习字符串和共享实例的能力了。这篇 msdn 文章介绍了为什么将 Tuple 设为引用类型。

If it is small and immutable then making it a struct would be preferable. Especially if you are going to have large collections of lots of Points. If you have a list of 1 million Points, then there will be lots of overhead for all those objects, in terms of both GC time and the 16 bytes of additional overhead per object instance.

String has to be a reference type because you cant and wouldn't want to store a variable number of characters on a stack, not to mention the ability to intern strings and share instances. This msdn article has information on why Tuple was made a reference type.

醉态萌生 2024-12-06 19:59:39

将其保留为一个类,除非它足够小以至于结构有意义。这将是罕见的。我的想法是,一般来说,“结构性”的情况正在迅速减少。如果在语言的开始就融入了更强的语义(不变性和域值对象功能),我会改变主意。作为一个相当新的示例,请考虑 System.Tuple<>。也就是说,我会稍微回避一下,问一下你的对象是什么(从修辞上来说)。

Keep it as a class unless it is small enough that struct makes sense. This will be rare. My thought is that generally speaking the cases for "structness" are rapidly diminishing. If stronger semantics were baked in at the beginnings of the language (immutability and domain value object features) I'd change my mind. As a fairly new example, consider System.Tuple<>. That said, I'd hedge slightly by asking, just what your object is (rhetorically speaking).

梦一生花开无言 2024-12-06 19:59:39

这实际上取决于您想要/需要什么来表示其中包含的数据。结构通常用于简单表示或用于保存您可能需要反复使用的多个值,并且当对象本身具有需要完成的某些必需行为时,应使用类。在您的情况下,为了简单起见并允许您保留您的属性,您不妨将其作为一个类。

不变性用于某些场景。例如,如果您希望某个东西每次更改时都是一个全新的对象,那么您可能需要考虑不变性(数据约束等)。如果您希望能够传递一个包含您不想更改的非常具体的信息的类(可能是数据库中的一些 DTO 对象,这些对象仅创建然后不进行任何更改地传递),这样您就不会出现奇怪的行为有人改变了一个值。

It really depends on what you want/need to represent the data contained within it. Structs are usually for simple representation or using to to hold multiple values that you may need over and over and classes should be used when the object itself has some required behavior that it needs to accomplish. In your case for the sake of simplicity and allowing you to keep your properties you might as well make this a class.

Immutability is used in some scenarios. For instance if you want something to be a completely new object every time it's changed then you may want to consider immutability (data constraints and such). If you want to be able to pass a class around with very specific information that you do not want changed (maybe some DTO objects from a database that are only created and then passed around with no changes) so that you do not get odd behavior if someone changes a value.

暖阳 2024-12-06 19:59:39

我不会为了不变性而改变结构。结构体和类之间最大的区别是结构体是值类型,而类是引用类型。结构在传递给方法时会被复制,但传递给方法的类将通过引用传递。类和结构一样可以是不可变的。

I wouldn't change to a struct for immutability. The biggest difference between a struct and a class is that a struct is a value type and a class is reference type. Structs are copied when passed to a method, but classes passed to a method will be passed by reference. Classes can be immutable just as well as stucts.

宁愿没拥抱 2024-12-06 19:59:39

不可变结构和密封不可变类类型对象的语义几乎相同。 16 字节及更小的结构体的性能通常会优于其他相同的类类型对象的性能,除非此类结构体类型转换为 Object 或接口类型;这种类型转换会极大地降低结构的性能,但不会特别影响类类型的性能。请注意,以下两者之间存在巨大差异:

  void doSomethingWithIFoo(IFoo whatever);

  void doSomethingWithIFoo<T>(T whatever) where T:IFoo;

将结构传递给前者将要求将结构类型转换为接口类型,而第二种形式将允许将结构作为其自己的类型进行处理。

The semantics of immutable structs and sealed immutable class-type objects are nearly identical. The performance of structs 16 bytes and smaller will generally be better than the performance of otherwise-identical class-type objects, except when such structs are typecast to Object or an interface type; such typecasts will greatly degrade the performance of structs, but not particularly affect the performance of class types. Note that there is a huge difference between:

  void doSomethingWithIFoo(IFoo whatever);

and

  void doSomethingWithIFoo<T>(T whatever) where T:IFoo;

Passing a struct to the former will require that the struct be typecast to an interface type, while the second form will allow the struct to be handled as its own type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文