问题
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;
}
回答1:
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
回答2:
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;}
}
回答3:
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.
来源:https://stackoverflow.com/questions/6573943/circular-reference-in-domain-model-using-c-sharp-struct