使用 C# 结构体在域模型中循环引用

发布于 2024-11-18 16:02:59 字数 270 浏览 8 评论 0原文

当两个结构之间存在循环引用时会发生什么?对于下面的示例,内存分配是如何工作的,或者会产生错误吗?

    public struct MultipleChoiceQuestion
    {
        public IEnumerable<Option> Options;
    }

    public struct Option
    {
        public MultipleChoiceQuestion Question;
    }

What happens when there is a circular reference between two structs? How does memory allocation work for the example below or would it yield and error?

    public struct MultipleChoiceQuestion
    {
        public IEnumerable<Option> Options;
    }

    public struct Option
    {
        public MultipleChoiceQuestion Question;
    }

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

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

发布评论

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

评论(3

扮仙女 2024-11-25 16:02:59

MultipleChoiceQuestion 中的 Options 字段只是一个参考,默认情况下为 nullOption 中的 Question 字段是一个 MultipleChoiceQuestion 类型的值,默认情况下将具有默认值。这里没有问题(除了在多种方面存在问题的设计之外)。

导致逻辑内存问题的真正循环引用将无法编译:

struct Foo
{
    Bar bar;
}

struct Bar
{
    Foo foo;
}

Test.cs(6,9):错误CS0523:“Bar”类型的结构成员“Foo.bar”导致结构布局中出现循环
Test.cs(11,9):错误CS0523:“Foo”类型的结构成员“Bar.foo”导致结构布局中出现循环

The Options field in MultipleChoiceQuestion is just a reference here, which will be null by default. The Question field in Option is a value of type MultipleChoiceQuestion which will have its default value by default. There's no problem here (other than a questionable design in more ways than one).

A genuine circular reference leading to a logical memory problem will fail to compile:

struct Foo
{
    Bar bar;
}

struct Bar
{
    Foo foo;
}

Test.cs(6,9): error CS0523: Struct member 'Foo.bar' of type 'Bar' causes a cycle in the struct layout
Test.cs(11,9): error CS0523: Struct member 'Bar.foo' of type 'Foo' causes a cycle in the struct layout

此刻的回忆 2024-11-25 16:02:59

问题(属性)是封装;问题是外部结构的一部分,通过字段。

然而,选项是对产生一个或多个选项的外部对象的引用;每次都会复制这些内容。

这里还有其他几个错误:

  • 可变结构:EVIL
  • 公共字段:EVIL
  • 选项作为列表会更好;并非所有枚举都是可重复的,
  • 它们不是“值” - 所以它们不应该是结构体; 在我看来,使用类来代替

public class MultipleChoiceQuestion
{
    private readonly List<Option> options
        = new List<Option>();
    public IList<Option> Options {get { return options; } }
}

public class Option
{
    public MultipleChoiceQuestion Question {get;set;}
}

Question (property) is encapsulation; the question is part of the outer struct, via a field.

Options, however, is a reference to an external object that yields one or more Options; these will be copied each time.

There are several other mistakes here:

  • mutable structs: EVIL
  • public fields: EVIL
  • the Options would be better as a list; not all enumerables are repeatable
  • they aren't "values" - so they should not be structs; use classes instead

IMO:

public class MultipleChoiceQuestion
{
    private readonly List<Option> options
        = new List<Option>();
    public IList<Option> Options {get { return options; } }
}

public class Option
{
    public MultipleChoiceQuestion Question {get;set;}
}
追我者格杀勿论 2024-11-25 16:02:59

MultipleChoiceQuestion 将仅具有对 IEnumerable 对象的引用(指针),因此堆栈上该结构的大小将是单个 IntPtr(在 x86 计算机上为 4 个字节)。

Option 结构将具有相同的大小,因为它仅包含 MultipleChoiceQuestion 结构。

The MultipleChoiceQuestion will simply have a reference (pointer) to an object that is IEnumerable, so the size of that struct on the stack will be a single IntPtr (4 bytes on an x86 machine).

The Option struct will have the same size, because it contains only the MultipleChoiceQuestion struct.

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