سؤال

ما أفهمه هو أنك عادة من المفترض أن استخدام xor مع GetHashCode() لإنتاج الباحث إلى تحديد البيانات الخاصة بك عن طريق قيمتها (بدلا من إشارته).وهنا مثال بسيط:

class Foo
{
    int m_a;
    int m_b;

    public int A
    {
        get { return m_a; }
        set { m_a = value; }
    }

    public int B
    {
        get { return m_b; }
        set { m_b = value; }
    }

    public Foo(int a, int b)
    {
        m_a = a;
        m_b = b;
    }

    public override int GetHashCode()
    {
        return A ^ B;
    }

    public override bool Equals(object obj)
    {
        return this.GetHashCode() == obj.GetHashCode();
    }
}

الفكرة التي أريد مقارنة مثيل واحد من فو إلى آخر على أساس قيمة الممتلكات A و B.إذا Foo1.A == Foo2.و Foo1.ب == Foo2.ب ، ثم لدينا المساواة.

هنا المشكلة:

Foo one = new Foo(1, 2);
Foo two = new Foo(2, 1);

if (one.Equals(two)) { ... }  // This is true!

هذه كل إنتاج القيمة من 3 GetHashCode () ، مما تسبب يساوي() إلى العودة الحقيقية.ومن الواضح أن هذا هو تافهة سبيل المثال ، مع اثنين فقط من خصائص لا يمكن ببساطة قارن بين الخصائص الفردية في يساوي (طريقة).ومع ذلك, مع المزيد من الدرجة المعقدة وهذا من شأنه أن يخرج عن السيطرة بسرعة.

وأنا أعلم أنه في بعض الأحيان فمن المنطقي جيدة لتعيين رمز التجزئة مرة واحدة فقط ، والعودة دائما نفس القيمة.ومع ذلك ، من أجل كائنات قابلة للتغيير حيث تقييم المساواة أمر ضروري, أنا لا أعتقد أن هذا هو المعقول.

ما هي أفضل طريقة للتعامل مع قيم العقارات التي يمكن بسهولة يكون متبادل عند تنفيذ GetHashCode()?

انظر أيضا

ما هو أفضل خوارزمية من أجل تجاوز النظام.الكائن.GetHashCode?

هل كانت مفيدة؟

المحلول

أولا - لا تنفذ يساوي() إلا من حيث الوقت() - hashcodes في بعض الأحيان تتصادم حتى عند الكائنات غير متساوية.

عقد GetHashCode() يتضمن ما يلي:

  • مختلفة hashcodes يعني أن الكائنات هي بالتأكيد ليست متساوية
  • نفس hashcodes يعني الأشياء قد تكون على قدم المساواة (ولكن ربما قد لا)

أندرو هير اقترح دمج جوابه:

أنصح أن تقرأ هذا الحل (لدينا الخاصة جدا جون السكيت, بالمناسبة) عن "أفضل" طريقة لحساب hashcode.

لا, سبق بطيئة نسبيا ، لا يساعد كثيرا.بعض الناس استخدام XOR (على سبيل المثال a ^ b ^ c) ولكن أنا أفضل نوع الأسلوب هو موضح في جوش بلوخ "فعالية جافا":

public override int GetHashCode()
{
    int hash = 23;
    hash = hash*37 + craneCounterweightID;
    hash = hash*37 + trailerID;
    hash = hash*37 + craneConfigurationTypeCode.GetHashCode();
    return hash;
}

23 و 37 تعسفية الأرقام التي شارك رئيس الوزراء.

فائدة أعلى على XOR الأسلوب هو أنه إذا كان لديك نوع الذي فقد اثنين من القيم التي في كثير من الأحيان نفسه ، XORing تلك القيم سوف تعطي دائما نفس النتيجة (0) في حين أعلاه التفريق بينهما إلا إذا أنت محظوظ جدا.

كما ذكر في أعلاه مقتطف قد تحتاج أيضا إلى النظر في جوشوا بلوخ كتاب فعالة جافا ، الذي يحتوي على معاملة لطيفة من موضوع (hashcode مناقشة ينطبق على .صافي كذلك).

نصائح أخرى

أندرو وقد نشرت مثال جيد لتوليد أفضل رمز التجزئة ، ولكن أيضا أن نأخذ في الاعتبار أنه يجب أن لا تستخدم تجزئة رموز المساواة الاختيار, لأنها ليست مضمونة أن تكون فريدة من نوعها.

بالنسبة تافهة مثال على السبب في هذا هو النظر في ضعف الكائن.فقد أكثر من القيم الممكنة من الباحث لذلك فمن المستحيل أن يكون فريد من نوعه int لكل مزدوجة.التجزئة هي في الحقيقة مجرد مرور الأول ، وتستخدم في حالات مثل القاموس عندما تحتاج إلى العثور على المفتاح بسرعة قبل الأولى مقارنة التجزئات نسبة كبيرة من الممكن مفاتيح يمكن استبعاد فقط مع مفاتيح مطابقة التجزئة تحتاج إلى أن يكون حساب المساواة الكاملة في الاختيار (أو غيرها تصادم القرار أساليب).

تجزئة ينطوي دائما التصادم لديك للتعامل معها (و.ه. ، مقارنة قيم التجزئة و إذا كانت متساوية ، بالضبط مقارنة القيم الموجودة داخل الفصول للتأكد من حصص متساوية).

باستخدام XOR بسيطة, سوف تحصل على العديد من الاصطدامات.إذا كنت تريد أقل ، استخدام بعض الدوال الرياضية التي توزع القيم عبر مختلف بت (bit التحولات ، تتضاعف مع الزمن.... الخ).

قراءة تجاوز الوقت بالنسبة قابلة للتغيير الكائنات ؟ C# والتفكير في تنفيذ IEquatable<T>

سريع توليد و توزيع جيد من الحشيش

public override int GetHashCode()
{
    return A.GetHashCode() ^ B.GetHashCode();         // XOR
}

من باب الفضول منذ hashcodes عادة ما تكون فكرة سيئة وعلى سبيل المقارنة ، لن يكون من الأفضل أن تفعل البرمجية التالية, أو أنا في عداد المفقودين شيئا ؟

public override bool Equals(object obj)
{
    bool isEqual = false;
    Foo otherFoo = obj as Foo;
    if (otherFoo != null)
    {
        isEqual = (this.A == otherFoo.A) && (this.B == otherFoo.B);
    }
    return isEqual;
}

هناك العديد من أفضل تجزئة التنفيذ. FNV تجزئة على سبيل المثال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top