是否可以仅使用值类型创建参考周期?

Wes*_*ill 5 .net serialization struct reference value-type

作为解释,请在C#中使用此值类型:

struct ObjRef
{
    public object Value;
    public ObjRef(object value) { Value = value; }
}
Run Code Online (Sandbox Code Playgroud)

我可以想象一个对象图,其中有两个这种类型的盒装实例,每个实例都包含对另一个的引用.这就是我所说的仅具有值类型的引用循环.

我的问题是这样的对象图是否可以在.NET中构建.从概念上讲,如果存在,构造将如下所示:

object left = new ObjRef();
object right = new ObjRef(left);
left.Value = right;
Run Code Online (Sandbox Code Playgroud)

但显然,最后一行没有有效的C#.制作最后一行:

((ObjRef)left).Value = right;
Run Code Online (Sandbox Code Playgroud)

没有达到结果,因为强制转换left,你最终会改变副本.所以至少在直接的C#中,它看起来不像是可能的.

有人知道是否可以使用反射,不安全代码dynamic,IL代码或任何其他方式实现构造?或者,任何人都可以证明CLR有效地阻止了这样的参考周期吗?

请注意,我实际上并不想创建这样的对象图.相反,答案可能会影响与对象图一起使用的算法的设计,例如序列化/反序列化格式化程序.


编辑

正如Brian建议的那样,确实可以通过将其转换为接口类型而不是值类型来修改盒装值而不将其取消装箱.所以给出这段代码:

interface IObjRef
{
    IObjRef Value { get; set; }
}

struct ObjRef : IObjRef
{
    IObjRef value;
    public IObjRef Value { get { return value; } set { this.value = value; } }
    public ObjRef(IObjRef value) { this.value = value; }
}
Run Code Online (Sandbox Code Playgroud)

那么我描述的参考周期可以这样构造:

IObjRef left = new ObjRef();
IObjRef right = new ObjRef(left);
left.Value = right;
Run Code Online (Sandbox Code Playgroud)

这基本上让我们理性#72为什么可变的价值类型是邪恶的.

Jar*_*Par 2

通过使用接口并让值类型实现该接口并相互引用,可以实现这一点。这允许他们通过装箱值创建循环,因为与接口引用一起使用时的结构将被装箱。

快速样品

interface ICycle
{
    void SetOther(ICycle other);
}

struct Cycle : ICycle
{
    ICycle value;
    public void SetOther(ICycle other)
    {
        value = other;
    }
}

class Example
{
    static void CreateCycle()
    {
        ICycle left = new Cycle();   // Left is now boxed
        ICycle right = new Cycle();  // Right is now boxed
        left.SetOther(right);
        right.SetOther(left);  // Cycle
    }
}
Run Code Online (Sandbox Code Playgroud)

我同意布莱恩的问题,但想知道这会给你带来什么好处。