views:

231

answers:

3

I'm looking for a way to sort a list of object (of any type possible) so that whatever happens to the objects, as long as they are not destructed, the order keeps the same (so the hashCode isn't a good idea because in some classes it's changing over a time), for that reason I was thinking to use the address of the object in the memory but I'm not sure that this always keeps the same (Can the address change by a garbage collecting call for instance?). However I'm looking for properties of objects (of any type) that will keep the same as long as the object isn't destroyed. Are there any of them? And if yes, what are they?

A: 

Sorting by memory address is only possible of reference objects of course. So not all types are possible to be sorted this way, primitive types and structs are not.

The other way is to depend on a certain interface, where you require that each of this instances can return a Guid. This is created in the constructor and not changed.

public interface ISortable
{
  Guid SortId { get; }
}

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

The advantage of a guid is that it could be created independently in each class. You need no synchronization, you just give every class an id.

By the way: If you are using the objects in a Dictionary as a Key, they must not change their hash code. They must be immutable. This could probably be a constraint you could depend on.


Edit: you could write your specialized list that is able to keep orderings.

Either you store the original order when the list is created from another list, and then you're able to restore the order at any point in time. New items could be put at the end. (are there new items anyway?)

Or you do something more sophisticated and store the order of any object that has ever be seen by your list class in a static memory. Then you can sort all the lists independently. But beware of the references you are holding, which will avoid the objects be cleaned up by the GC. You'll need week references, I think there are weak references in C# but I've never used them.

Even better would be to put this logic into a sorting class. So it works for every list that has been sorted by your sorting class.

Stefan Steinegger
+1  A: 

Updated given the detail now added to the question (comments); just take a copy of the list contents before you sort it...


No the address is not fixed. And for arbitrary objects, no there is no sensible way of doing this. For your own objects you could add something common, like:

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();
    }
}

A bit scrappy, but it should work, and could be used in a base-class. The Order is now non-changing and sequential. But only AppDomain-specific, and not all serialization APIs will respect it (you'd need to use serialization-callbacks to initialize the sequence in such cases).

Marc Gravell
+1  A: 

Yes, objects can be moved around in memory by the garbage collector, unless you specifically ask it not to (and it's generally recommended to let the GC do its thing).

What you need here is a side table: create a dictionary keyed by the objects themselves, and for the value put anything you like (could be the original hashcode of the object, or even a random number). When you sort, sort by that side key. Now if for example the object a has value "1" in this dictionary, it'll always be sorted first - regardless of what changes are made to a, because you'll look in your side dictionary for the key and the code for a doesn't know to go there and change it (and of course you are careful to keep that data immutable). You can use weak references to make sure that your dictionary entries go away if there is no other reference to the object a.

redtuna