2009-08-26 49 views
1

我正在寻找一种方法来排序对象列表(任何可能的类型),以便无论发生在对象,只要他们没有被破坏,顺序保持不变(所以hashCode不是一个好主意,因为在某些类中它会随时间变化),因此我在考虑在内存中使用对象的地址,但我不确定它总是保持不变(例如,垃圾收集呼叫可以改变地址吗?)。然而,我正在寻找对象的属性(任何类型),只要对象没有被销毁,这些属性也会保持不变。他们有没有?如果是的话,他们是什么?在C中的对象的不可变属性#

+0

不确定你究竟是什么后,你可不要简单地创建一个数组,其中包含一个id引用的对象。那么简单地让这些对象负责在创建它们时自己添加它们,并在它们被破坏时将它们从列表中取出来? – Darknight 2009-08-26 11:40:08

+0

你的问题似乎有点奇怪,也许如果你试图解释你试图解决的问题,你会得到答案,避免你目前面临的问题。回答你的一个问题:在垃圾收集期间,.NET对象在内存中移动,但在托管环境中,你永远不应该使用对象地址。 – 2009-08-26 11:44:33

+0

我希望evry数组对象的顺序相同,所以如果你制作了一个列表副本(不是深拷贝,是对象的rhe引用的副本),并且你洗牌第二个数组,你可以很容易地使用正确的顺序,因为不变的属性。可以访问的某些值可以确保evry对象具有特定的顺序,从而不依赖于对象本身的内容。 – 2009-08-26 11:47:51

回答

2

是的,对象可以通过垃圾收集器在内存中移动,除非你明确地要求它不要(并且通常建议让GC做它的事情)。

这里需要的是一个边桌:创建一个由对象自己键入的字典,并为值放上你喜欢的任何东西(可以是对象的原始哈希码,甚至是随机数)。在排序时,按该侧键进行排序。现在,如果例如对象a在该字典中的值为“1”,它将总是首先排序 - 无论a做了什么更改,因为您会在侧面字典中查找关键字和代码不知道去那里改变它(当然,你要小心保持这个数据不变)。您可以使用weak references来确保您的字典条目在没有其他对象引用的情况下消失。

0

当然,只能通过内存地址进行排序。所以不是所有类型都可以按照这种方式排序,原始类型和结构不是。

另一种方式是依赖于某个接口,你需要每个实例都可以返回一个Guid。这是在构造函数中创建的,没有改变。

public interface ISortable 
{ 
    Guid SortId { get; } 
} 

class Foo : ISortable 
{ 
    Foo() 
    { 
    SortId = Guid.NewGuid(); 
    } 
    Guid SortId { get; private set; } 
} 

guid的优点是它可以在每个类中独立创建。你不需要同步,你只需给每个班级一个ID。顺便说一句:如果你使用字典中的对象作为一个键,他们不能改变它们的哈希码。它们必须是不可变的。这可能是你可能依赖的一个限制。


编辑:你可以写你的专业列表,能够保持排序。

当您从另一个列表创建列表时,您可以存储原始订单,然后您可以在任何时间点恢复订单。新的项目可以放在最后。 (有没有新的东西?)

或者你做一些更复杂的事情,并存储任何你的列表类在静态存储器中看到的任何对象的顺序。然后您可以独立地对所有列表进行排序。但是要小心你拿着的参考物,这样可以避免GC清理物体。你需要一周参考,我认为在C#中有弱引用,但我从来没有使用它们。

更好的办法是把这个逻辑放到排序类中。所以它适用于您的排序类进行排序的每个列表。

1

更新后的细节现在添加到问题(评论);只需在列表内容的副本之前对其进行分类...


否地址不固定。对于任意物体,没有没有明智的做法。为了您自己对象,你可以添加一些共同点,如:

interface ISequence { int Order { get; } } 
static class Sequence { 
    private static int next; 
    public static int Next() { 
     return Interlocked.Increment(ref next); } 
} 
class Foo : ISequence { 
    private readonly int sequence; 
    int ISequence.Order { get { return sequence; } } 
    public Foo() { 
     sequence = Sequence.Next(); 
    } 
} 

有点零碎,但它应该工作,并且可以在一个基类中使用。 Order现在是不变的和顺序的。但只有AppDomain特定的,并不是所有的序列化API都会尊重它(在这种情况下,您需要使用序列化回调来初始化序列)。

相关问题