2009-08-26 3 views
1

Я ищу способ сортировки списка объектов (любого типа), чтобы все, что происходит с объектами, до тех пор, пока они не разрушены, порядок сохраняет то же самое (поэтому hashCode не очень хорошая идея, потому что в некоторых классах он меняется с течением времени), поэтому я думал использовать адрес объекта в памяти, но я не уверен, что это всегда сохраняет то же самое (Может ли адрес сменить на вызов сбора мусора, например?). Однако я ищу свойства объектов (любого типа), которые будут сохраняться одинаково до тех пор, пока объект не будет уничтожен. Есть ли кто-нибудь из них? И если да, то каковы они?неизменяемые свойства объекта в C#

+0

Не уверен, что вы сделали после, не могли бы вы упростить создание массива, содержащего ссылку id на объекты. Тогда просто нужно, чтобы объекты отвечали за добавление себя, когда они созданы, и беря их из списка, когда они разрушаются? – Darknight

+0

Ваш вопрос кажется несколько странным, и, возможно, если вы попытаетесь объяснить проблему, которую пытаетесь решить, вы получите ответы, которые позволят избежать проблемы, с которой вы в настоящее время сталкиваетесь. Чтобы ответить на один из ваших вопросов: объекты .NET перемещаются в памяти во время сбора мусора, но в управляемом мире вы никогда не должны использовать адреса объектов. –

+0

Мне нужен тот же порядок для создания массива объектов, поэтому, если вы сделаете копию списка (а не глубокую копию, копию ссылок на объекты) и перетасовываете второй массив, вы можете легко применить его в правильный порядок из-за непреложного попринта. Некоторое значение, к которому можно получить доступ, и который обеспечивает определенный порядок для объекта evry для evry объекта, который не зависит от содержимого самого объекта. –

ответ

2

Да, объекты могут перемещаться в памяти сборщиком мусора, если вы специально не попросите его не делать (и обычно рекомендуется, чтобы GC выполнял свою задачу).

Что вам нужно, это боковая таблица: создайте словарь, на который накладываются сами объекты, и для значения ставьте все, что вам нравится (может быть исходный хэш-код объекта или даже случайное число). Когда сортировка сортируется по этой стороне. Теперь, если, например, объект a имеет значение «1» в этом словаре, он всегда будет отсортирован первым - независимо от того, какие изменения внесены в a, поскольку вы будете искать в своем боковом словаре для ключа и кода для не знает, чтобы пойти туда и изменить его (и, конечно же, вы стараетесь сохранить эти данные неизменными). Вы можете использовать weak references, чтобы убедиться, что ваши словарные записи исчезнут, если нет другой ссылки на объект a.

0

Сортировка по адресу памяти, конечно, возможно только для справочных объектов. Поэтому не все типы можно сортировать таким образом, примитивные типы и структуры не являются.

Другой способ заключается в том, чтобы зависеть от определенного интерфейса, где требуется, чтобы каждый из этих экземпляров мог вернуть Guid. Это создается в конструкторе и не изменяется.

public interface ISortable 
{ 
    Guid SortId { get; } 
} 

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

Преимущество руководства заключается в том, что он может быть создан независимо в каждом классе. Вам не нужна синхронизация, вы просто даете каждому классу идентификатор.

Кстати: если вы используете объекты в словаре как ключ, они не должны изменять свой хэш-код. Они должны быть неизменными. Вероятно, это может быть ограничение, от которого вы могли бы зависеть.


Edit: вы могли бы написать свой специализированный список, который способен держать упорядоченности.

Либо вы сохраняете первоначальный заказ, когда список создается из другого списка, а затем вы можете восстановить заказ в любой момент времени. Новые предметы можно было бы положить в конец. (есть ли новые предметы?)

Или вы делаете что-то более сложное и сохраняете порядок любого объекта, который когда-либо видел ваш класс списка в статической памяти. Затем вы можете сортировать все списки самостоятельно. Но остерегайтесь ссылок, которые вы держите, что позволит избежать очистки объектов 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-интерфейсы сериализации будут его уважать (вам нужно будет использовать сериализацию-обратные вызовы для инициализации последовательности в таких случаях).

Смежные вопросы