谁能告诉我ObjectIDGenerator如何更好(更糟?)然后在遍历对象层次结构(可能是recurvise / circular)时使用HashSet,而不想两次遍历同一个对象?
基本区别在于每个人如何平等。
ObjectIdGenerator查看引用标识。检查对象是否存在时,它只会对两个对象实例进行==调用。这将归结为参考比较,因为此时对象是静态类型为对象。除非您的对象显式使用.Equals()进行相等,否则这很好。如果两个对象通过.Equals()但不同的引用相等,则ObjectIDGenerator会将它们视为不同的对象。可能不是你想要的。
另一方面,HashSet允许您通过IEqualityComparer <T>参数自定义比较对象的方式。如果没有指定,它将使用EqualityComparer <T> .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
}