ObjectIDGenerator против HashSet <T> - PullRequest
1 голос
/ 22 января 2009

Может кто-нибудь сказать мне, как ObjectIDGenerator лучше (хуже?), Чем использовать HashSet при обходе иерархии объектов (которые могут быть рекурсивными / круговыми), и не хочет проходить один и тот же объект дважды?

1 Ответ

4 голосов
/ 22 января 2009

Основная разница в том, как каждый из них равенство.

ObjectIdGenerator просматривает ссылочную идентичность. При проверке, чтобы увидеть, присутствует ли объект уже, он просто сделает вызов == для двух экземпляров объекта. Это будет сводиться к эталонному сравнению, потому что объекты статического типа являются объектами в этой точке. Это нормально, если ваш объект явно не использует .Equals () для равенства. Если два объекта равны через .Equals (), но разные ссылки, ObjectIDGenerator будет считать их разными объектами. Скорее всего, не то, что вы хотите.

С другой стороны, HashSet позволяет настроить способ сравнения объектов с помощью параметра IEqualityComparer . Если ничего не указано, он будет использовать EqualityComparer .Default, который будет использовать равенство значений. Этот метод вызывает метод .Equals () и зависит от него, чтобы определить, равны ли два объекта. В случае, если вы не определили метод .Equals () для ваших типов, он по умолчанию вернется к ссылочному равенству, что почти наверняка вам нужно.

Короче, иди с HashSet:)

Пример кода, показывающий разницу:

class Person
{
    public readonly string Name;
    public Person(string name) { Name = name; }
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        var other = obj as Person;
        if (other == null)
        {
            return false;
        }
        return StringComparer.Ordinal.Equals(Name, other.Name);
    }
}

public static void Example()
{
    var gen = new ObjectIDGenerator();
    bool isFirst;
    var person1 = new Person("John");
    var person2 = new Person("Bob");
    gen.GetId(person1, out isFirst);    // isFirst = true
    gen.GetId(person1, out isFirst);    // isFirst = false
    gen.GetId(person2, out isFirst);    // isFirst = true
    gen.GetId(new Person("John"), out isFirst); // isFirst = true even though they are .Equals()

    var set = new HashSet<Person>();
    set.Add(person1);
    var contains1 = set.Contains(person1);              // true
    var contains2 = set.Contains(new Person("John"));   // true
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...