使用引用类型成员定义结构体是否有意义?

发布于 2024-10-31 07:27:10 字数 207 浏览 2 评论 0原文

使用引用类型成员定义结构(而不​​是将其定义为类)是否有意义?例如,要定义此结构:

public struct SomeStruct
{
    string name;
    Int32  place;
}

我问是因为我知道结构是值类型,并且在其中定义某些引用类型没有任何意义。

我说得对吗?有人可以解释一下吗?

Is there any sense in defining a struct with a reference type member (and not defining it as a class)? For example, to define this struct:

public struct SomeStruct
{
    string name;
    Int32  place;
}

I asking because I know that a struct is a value type, and to define in it some reference type does not make any sense.

Am I right? Can someone explain this?

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

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

发布评论

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

评论(4

み格子的夏天 2024-11-07 07:27:10

十分之九,您首先应该创建类而不是结构。例如,与 C++ 中的结构和类相比,C# 中的结构和类具有非常不同的语义。大多数使用结构的程序员应该使用过类,坦率地说,这样的问题是无关紧要的。

以下是一些关于何时应该选择结构而不是类的快速规则:

  1. 永远不要。
    ...哦,你还在看书吗?你很执着。好的,很好。
  2. 当您明确需要值类型语义(而不是引用类型语义)时。
  3. 当您的类型非常小时(经验法则是内存占用量小于 16 字节)。
  4. 当您的结构所表示的对象将是短暂的且不可变(不会改变)时。
  5. 有时,出于与使用结构的本机代码的互操作目的。

但是,如果您做出了明智的决定并且确实有信心事实上,确实需要一个结构而不是一个类,您需要重新审视第 2 点并理解什么是值类型语义。 Jon Skeet 的文章应该对澄清这种区别大有帮助。

完成此操作后,您应该明白为什么在值类型(结构)内部定义引用类型不是问题。引用类型就像指针。结构体内部的字段不存储实际类型;相反,它存储指向该类型的指针(或引用)。使用包含引用类型的字段声明结构体并没有任何矛盾或错误。它既不会“减慢对象速度”,也不会“调用 GC”,这是您在评论中表达的两个问题。

Nine times out of ten, you should be creating a class rather than a structure in the first place. Structures and classes have very different semantics in C#, compared to what you might find in C++, for example. Most programmers who use a structure should have used a class, making questions like this one quite frankly irrelevant.

Here are some quick rules about when you should choose a structure over a class:

  1. Never.
    ...Oh, you're still reading? You're persistent. Okay, fine.
  2. When you have an explicit need for value-type semantics, as opposed to reference type semantics.
  3. When you have a very small type (the rule of thumb is a memory footprint less than 16 bytes).
  4. When objects represented by your struct will be short-lived and immutable (won't change).
  5. And occasionally, for interop purposes with native code that uses structures.

But if you've made an informed decision and are truly confident that you do, in fact, need a structure rather than a class, you need to revisit point number 2 and understand what value type semantics are. Jon Skeet's article here should go a long way towards clarifying the distinction.

Once you've done that, you should understand why defining a reference type inside of a value type (struct) is not a problem. Reference types are like pointers. The field inside of the structure doesn't store the actual type; rather, it stores a pointer (or a reference) to that type. There's nothing contradictory or wrong about declaring a struct with a field containing a reference type. It will neither "slow the object" nor will it "call GC", the two concerns you express in a comment.

夜灵血窟げ 2024-11-07 07:27:10

声明引用类型的字段意味着需要有空间来保存指向目标对象的引用的。因此,在结构中拥有这样的字段是非常有意义的。

Declaring a field of a reference type means there needs to be space to hold the value of the reference that is pointing to the target object. Thus it makes perfect sense to have such fields in structs.

乖乖兔^ω^ 2024-11-07 07:27:10

一般来说,如果满足以下条件之一,结构体应该只包含引用类型的公共和/或可变字段:

  1. 该类型的所有实例都可以被视为本质上不可变(就像“string”的情况)
  2. 该结构体的语义清楚地表明字段标识它所引用的对象,而不是封装其状态,并且该字段所引用的对象的状态不是 i> 被视为结构的一部分。例如,在 KeyValuePair中,人们会期望“Value”来标识表单实例;在屏幕上移动表单会更改“Value.Bounds”,但不会被视为更改“Value”(无论其在屏幕上的位置如何,它将继续引用相同的表单)

如果这两个条件都不适用,则在满足以下所有条件的情况下,结构体保存引用类型的字段可能是合适的:

  1. 该字段从不保存对结构体本身未创建的任何可变对象的引用。
  2. 引用绝不能暴露给任何将来可能会改变它所引用的对象的代码,也不能暴露给任何代码。
  3. 在字段要引用的对象上进行的所有更改都必须在引用存储在字段中之前执行。

换句话说,如果没有可以修改对象引用的执行路径,则用于封装对象状态(而不是仅仅标识对象)的对象引用仅应存储在结构体字段中。

In general, a struct should only contain a public and/or mutable field of a reference type if one of the following conditions applies:

  1. All instances of that type may be regarded as inherently immutable (as is the case of `string`)
  2. The semantics of the struct clearly imply that the field identifies the object to which it refers, rather than encapsulating its state, and that the state of the object referred to by the field is not considered part of the struct. For example, in a KeyValuePair<string, Form>, one would expect the `Value` to identify a form instance; moving the form around the screen would change `Value.Bounds`, but would not be considered to change `Value` (which would continue to refer to the same form, regardless of its on-screen location)

If neither condition applies, it may be appropriate for a structure to hold a field of a reference type provided all of the following conditions apply:

  1. The field never holds a reference to any mutable object which the struct did not itself create.
  2. The reference must never be exposed, nor ever have been exposed, to any code that might in future mutate the object it refers to.
  3. All mutations that are ever going to be done on the object to which the field is going to refer must be performed before a reference is stored in the field.

In other words, an object reference which is used to encapsulate the state of an object (as opposed to merely identifying it) should only be stored in a struct field if there is no execution path via which the object to which it refers might be modified.

青春有你 2024-11-07 07:27:10

我很想听听更有经验的程序员对此的优缺点有何看法,但我的理解是,作为值类型,SomeStruct 类型的变量将从堆栈中分配,但将包含对包含该字符串的堆上位置的引用。

I'm interested to hear what more experienced coders have to say about the pros and cons of this, but my understanding is that, as a value type, a variable of type SomeStruct would be allocated from the stack, but would contain a reference to the location on the heap containing the string.

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