我怎样才能实例不变相互递归对象? [英] How can I instantiate immutable mutually recursive objects?

查看:118
本文介绍了我怎样才能实例不变相互递归对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个不变的递归类型:

I have an immutable recursive type:

public sealed class Foo
{
    private readonly object something;
    private readonly Foo other; // might be null

    public Foo(object something, Foo other)
    {
        this.something = something;
        this.other = other;
    }
    public object Something { get { return something; } }
    public Foo Other { get { return other; } }
}



我需要实例化这种类型的两个对象引用彼此,即 a.Other == b和;&安培; b.Other == A

我不想放弃永恒不变,因为拟用作轻量级。我可以(我认为必须)放弃只读上的字段,并留下了胆可变的,但公共接口必须是不可改变的。

I don't want to abandon the immutability invariants because Foo is intended for use as a flyweight. I can (and I think must) abandon readonly on the fields, and leave the "guts" mutable, but the public interface must be immutable.

时的冰棍不变性只有这样,才能完成这件事。

Is popsicle immutability the only way to get this done?

修改:我试图模拟一个集合类型。每种类型都有一个名字和几个属性。每个属性都有一个名称和类型。有几个相互递归类型,而这也正是这个问题的出现了。

EDIT: I'm trying to model a collection of types. Each type has a name and several attributes. Each attribute has a name and a type. There are a few mutually recursive types, and that's where this problem arose.

推荐答案

有其他的方法来完成它,但他们可能没有你想要的属性。

There are other ways to get it done, but they might not have properties that you want.

假设你想代表值的不可变树,从树叶构建的。这是非常简单的。你可能有一个节点构造函数的值和子节点列表。这使得它非常简单,构建新的树木了古树的,而且他们保证是无环的。

Suppose you wanted to represent an immutable tree of values, built from the leaves up. That's pretty straightforward. You might have a node constructor that takes a value and a list of child nodes. That makes it pretty straightforward to construct new trees out of old trees, and they're guaranteed to be acyclic.

现在假设你要代表值的不可变向图。现在你有一个节点可以有周期的问题;有可能不是一个叶,以建立从图。解决的办法是放弃原则,即节点的知道它的邻居是。你可以通过一个不可变组节点,和边的不可变列表代表一个不可改变的图形。要将节点添加到不可改变图形您构建与添加到节点组节点的新图。同样地,对于加入的边缘;你构造边的新名单。现在的事实是有图中的拓扑周期无关;没有任何一个对象中有引用什么对象的循环。

Now suppose you want to represent an immutable directed graph of values. Now you have the problem that nodes can have cycles; there might not be a "leaf" to build the graph from. The solution is to abandon the principle that the node knows what its neighbours are. You could represent an immutable graph by making an immutable set of nodes, and an immutable list of edges. To add a node to the immutable graph you construct a new graph with that node added to the node set. Similarly for adding an edge; you construct a new list of edges. Now the fact that there are cycles in the topology of the graph is irrelevant; no one object has a cycle in what objects it references.

不知道更多关于你的实际问题的空间,很难说什么一成不变的数据结构会为你的应用程序。你能告诉我们更多关于你想要做什么?

Without knowing more about your actual problem space it is hard to say what immutable data structure would work for your application. Can you tell us more about what you're trying to do?

我想要的类型集合模型。每种类型都有一个名字和几个属性。每个属性都有一个名称和类型。有几个相互递归类型,而这也正是这个问题的出现了。

I'm trying to model a collection of types. Each type has a name and several attributes. Each attribute has a name and a type. There are a few mutually recursive types, and that's where this problem arose.

好吧天啊,你应该这么说摆在首位。如果有一件事我知道,它的类型分析。显然,编译器需要能够处理各种疯狂的类型情况,包括类型的循环基类,周期涉及内部类型,类型参数,类型约束等等。

Well geez, you should have said so in the first place. If there's one thing I know about, it's analysis of types. Obviously the compiler needs to be able to handle all kinds of crazy type situations, including types with cyclic base classes, cycles involving inner types, type arguments, type constraints and so on.

在C#编译器我们主要通过使物体解决这些问题,在他们的不可改变的上演。也就是说,当我们第一次创建一组类型,每种类型的对象知道它的名字和它的源代码(或元数据)的位置。这个名字就成为不可改变的。然后,我们解决了基本类型,并检查它们的循环;基本类型进而成为不可改变的。然后我们检查的类型约束......那么,我们解决的属性...等等,直到一切都进行了分析。这样做的。

In the C# compiler we solve these problems mostly by making objects "staged" in their immutability. That is, when we first create a set of types, each type object knows its name and its position in source code (or metadata). The name then becomes immutable. We then resolve the base types and check them for cycles; the base types then become immutable. Then we check the type constraints... then we resolve the attributes... and so on, until everything is analyzed.

我已经考虑其他方式。例如,我们可能会使用我刚才建议的图表同样的技术:使一个不可变对象,叫,说编译,您可以向其中添加的类型,从而产生新的不可变的汇编。编译可以跟踪一个类型,它的基类型之间的边缘的一个不可变的哈希表,然后可以检查周期所产生的图形。向下侧然后,一个类型不知道它的基本类型;你要问编译什么类型的基本类型是。

I have considered other ways of doing this. For example, we might use the same technique that I just suggested for graphs: make an immutable object, called, say "compilation", to which you can add types, thereby producing new immutable compilations. The compilation can keep track of the "edges" between a type and its base type in an immutable hash map, and can then check the resulting graph for cycles. The down side is then that a type does not know its base type; you have to ask the compilation what the base type of a type is.

您可以在这里做同样的事情。你可以有一类排版包含一组不可变类型,并从类型多图一组不变的属性。你可以建立集的种类和设定,只要你喜欢的属性;改变的事情是在地图上,而不是类型。

You could do the same thing here. You could have a class "typeset" that contains a set of immutable types, and a multi-map from type to a set of immutable attributes. You can build up the set of types and the set of attributes however you like; the thing that changes is the map, not the type.

这样做的缺点是,你不再问的键入的为它的属性;你问一个类型的属性的排版。如果您需要独立周围的任何排版的传递类型,可能无法满足您的需求。

The down side of this is that you no longer ask the type for its attributes; you ask the typeset for the attributes of a type. That might not meet your needs if you need to pass types around independently of any typeset.

这篇关于我怎样才能实例不变相互递归对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆