-4

参照型オブジェクトがあり、同じ属性を持つ 2 つのオブジェクトを作成した場合、それらは同じハッシュ コードを持ちますか?

サンプルクラス:

class Person
{
   int id;
   string name;

   public Person(int pid, string pname)
   {
      this.id = pid;
      this.name = pname;
   }
}

次に、2 つのオブジェクトを定義します。

Person p1 = new Person(1,"xxx");
Perdon p2 = new Person(1,"xxx");

//p1.GetHashCode() = p2.GetHashCode() ??

編集:私はこのコードを試してみましたが、異なる結果が得られましたが、文字列でテストした
ところ、私が求めているのと同じ結果が得られました

4

4 に答える 4

1

デフォルトの実装については、こちらを参照してください: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

GetHashCode メソッドの既定の実装では、異なるオブジェクトに対して一意の戻り値が保証されるわけではありません。さらに、.NET Framework は GetHashCode メソッドの既定の実装を保証しておらず、返される値は .NET Framework の異なるバージョン間で同じになります。したがって、このメソッドのデフォルトの実装は、ハッシュ目的で一意のオブジェクト識別子として使用しないでください。

しかし、皆さんが本当に知りたいと思うのは、ハッシュ コードがどのように機能するかということです。

次のクラスがあるとします。

public Person
{
    private string name;
    public Person(Name name)
    {
        this.name = name;
    }
}

では、2 人の人物を比較して、同じ名前かどうかを確認したいとします。これはどのように行うのでしょうか? Object に実装されている equals をオーバーライドします。(C# のすべてのクラスは Object を暗黙的に継承します) 以下のように:

public Person
{
    private string name;
    public Person(Name name)
    {
        this.name = name;
    }

    public override bool Equals(Object obj)
    {
        if(obj == null)
            return false // not equal if obj is null

        Equals temp = obj as Equals; // temp set to null if obj can not be cast to equals
        if(p == null)
            return false

        // if code gets here, the code object passed is an instance of Equals.
        // Now we have to check if the strings match.
        bool isEqual = p.name == this.name; // set if the two names match
        return isEqual; // return if these two match
    }
}

これで、2 人が等しいかどうかを確認できます。例:

Person p1 = new Person("Jack");
Person p2 = new Person("Jack");
Person p3 = new Person("Jill");
Object p4 = new Person("Jill");

p1.Equals(p2) // returns true
p1.Equals(p3) // returns false
p4.Equals(p1) // returns false
p4.Equals(p3) // returns true

"amy"ここで、100 万人のような膨大な人のリストがあり、その名前の人物がこのリストに存在するかどうかを知りたいとしましょう。どうやってこの人を見つけますか?すべての名前を 1 つずつループして、その Person が amy と等しいかどうかを確認しますか? しかし、それは非常に遅いでしょう.エイミーがこのリストの100万人目の人物だったらどうなるでしょうか? どうすればパフォーマンスを改善できますか?

ハッシュコードを入力します。

簡単なハッシュコード アルゴリズムを作成するとします。ハッシュコードは、人物名の各文字の各数字の合計です。

public Person
{
    private string name;
    public Person(Name name)
    {
        this.name = name;
    }

    public  override bool Equals(Object obj)
    {
        if(obj == null)
            return false // not equal if obj is null

        Equals temp = obj as Equals; // temp set to null if obj can not be cast to equals
        if(p == null)
            return false

        // if code gets here, the code object passed is an instance of Equals.
        // Now we have to check if the strings match.
        bool isEqual = p.name == this.name; // set if the two names match
        return isEqual; // return if these two match
    }

    public override int GetHashCode()
    {
        int sum = 0;
        foreach(char c in this.name)
        {
            sum += c;
        }
        return sum;
    }
}

したがって、amy彼女のハッシュコードがあれば1 + 13 + 25、そう38です。

通常のリストの代わりに、いわゆる「バケット」を含むリストがあります。ハッシュコードによって、どのバケットに移動するかが決まります。彼女がバケツにamy入った場合、ハスコードを持っています。3838

ここで、名前に別の人物がいるとしましょう。may彼女の名前には同じ文字が含まれているため、ハッシュコードもであり38、彼女もバケットに入ります38

さて、エイミーがこのリストに存在するかどうかを確認したいときはいつでも。最初に彼女のハッシュコードをチェックします。38今度はバケット 38 を調べ、バケット内のすべてのオブジェクトをループして、バケット内38のオブジェクトのいずれかが38amy と一致するかどうかを確認します。true の場合は true を返し、false の場合は false を返します。したがって、100 万人の人物がいる場合、このリストに存在するかどうかを知るために行う必要があるチェックのamyリストは大幅に削減されます。

したがって、基本的に、ハッシュコードを使用する場合は、次の規則に従う必要があります。

  • ハッシュコードを使用する場合は、equals をオーバーライドして実装する必要があります。
  • Equals が true を返す 2 つのオブジェクトの場合、それらは常に同じハッシュコードを持っている必要があります
  • 異なる 2 つのオブジェクトが同じハッシュコードを持つ場合がありますが、必ずしも同じである必要はありません。

それが基本的にその要点です。

于 2012-08-30T10:26:34.043 に答える
1

Person が構造体の場合、メンバーの値からハッシュコードが生成され、同じ結果が得られます。ただし、クラスの場合、デフォルトのハッシュコード実装は、メモリ参照に基づいて、各オブジェクトに一意のハッシュコードを提供します。

したがって、この場合、p1 と p2 に同じハッシュコードが必要な場合は、独自の実装を提供する必要があります。

于 2012-08-30T09:17:48.603 に答える
1

実装は自己責任でお願いしGetHashCodeます。そうしないと、ハッシュ コードが同じになるはずですが、同じハッシュ コードにはなりません。

于 2012-08-30T09:18:08.140 に答える
0

デフォルトではそうではありません (参照型の場合)。これを試してみてください。

それらに同じハッシュ コードを持たせたい場合は、それに応じて独自の GetHashCode() を記述する必要があります。

于 2012-08-30T09:18:31.150 に答える