在不存在的结构布局中循环

ala*_*ere 21 c# constructor struct member cyclic-reference

这是我的一些代码的简化版本:

public struct info
{
    public float a, b;
    public info? c;

    public info(float a, float b, info? c = null)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是Struct member 'info' causes a cycle in the struct layout.我在结构之后的错误,就像值类型行为一样.我可以使用类和克隆成员函数来模拟这个,但我不明白为什么我需要.

这个错误怎么样?在某些类似的情况下,递归可能会永远导致构造,但在这种情况下我无法想到它的任何方式.下面是程序编译时应该没问题的例子.

new info(1, 2);
new info(1, 2, null);
new info(1, 2, new info(3, 4));
Run Code Online (Sandbox Code Playgroud)

编辑:

我使用的解决方案是使"info"成为一个类而不是一个struct,并给它一个成员函数来返回我在传递它时使用的副本.实际上模拟与结构相同但具有类的行为.

我在寻找答案时也创建了以下问题.

C#中的值类型类定义?

Mar*_*ers 31

拥有一个包含自己作为成员的结构是不合法的.这是因为结构具有固定的大小,并且它必须至少与其每个成员的大小之和一样大.您的类型必须为两个浮点数提供8个字节,至少一个字节用于显示是否info为空,加上另一个浮点数的大小info.这给出了以下不等式:

 size of info >= 4 + 4 + 1 + size of info
Run Code Online (Sandbox Code Playgroud)

这显然是不可能的,因为它需要你的类型无限大.

您必须使用引用类型(即类).您可以使您的类不可变并覆盖EqualsGetHashCode提供类似于String类的类似行为的行为.


Jar*_*Par 11

这创造一个循环的原因是它Nullable<T>本身就是一个struct.因为它指的是info你在布局中有一个循环(info有一个字段,Nullable<info>它有一个字段info).它基本上等同于以下内容

public struct MyNullable<T> {
  public T value;
  public bool hasValue;
}

struct info { 
  public float a, b;
  public MyNullable<info> next;
}
Run Code Online (Sandbox Code Playgroud)


das*_*ght 5

真正的问题在于这一行:

public info? c;
Run Code Online (Sandbox Code Playgroud)

由于这是一个struct,C# 需要知道内部info/s 布局,然后才能生成外部info布局。并且内部info包括内部内部info,内部内部又包括内部内部内部info,依此类推。由于此循环引用问题,编译器无法生成布局。

注意:info? c是一个简写,Nullable<info>它本身就是一个struct.