ObjectIDGenerator与HashSet <t> </t>

时间:2009-01-22 17:36:58

标签: .net hash

有人能告诉我ObjectIDGenerator如何更好(更糟糕?)然后在遍历对象层次结构时使用HashSet(可能是recurvise / circular),而不想两次遍历同一个对象?

1 个答案:

答案 0 :(得分:4)

基本区别在于每个人如何平等。

ObjectIdGenerator查看引用标识。检查对象是否存在时,它只会对两个对象实例进行==调用。这将归结为参考比较,因为此时对象是静态类型为对象。除非您的对象显式使用.Equals()进行相等,否则这很好。如果两个对象通过.Equals()但不同的引用相等,则ObjectIDGenerator会将它们视为不同的对象。可能不是你想要的。

另一方面,

HashSet允许您通过IEqualityComparer&lt; T&gt;自定义比较对象的方式。参数。如果没有指定,它将使用EqualityComparer&lt; T&gt; .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
}