Основная разница в том, как каждый из них равенство.
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
}