Object.GetHashCode Yöntem
Tanım
Önemli
Bazı bilgiler ürünün ön sürümüyle ilgilidir ve sürüm öncesinde önemli değişiklikler yapılmış olabilir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.
Varsayılan karma işlevi işlevi görür.
public:
virtual int GetHashCode();
public virtual int GetHashCode();
abstract member GetHashCode : unit -> int
override this.GetHashCode : unit -> int
Public Overridable Function GetHashCode () As Integer
Döndürülenler
Geçerli nesne için karma kod.
Örnekler
Sayısal bir değer için, Int32 türüyle aynı veya daha küçük bir aralığı olan bir karma kodu hesaplamanın en basit yollarından biri sadece bu değeri iade etmektir. Aşağıdaki örnekte bir Number yapısının böyle bir uygulaması gösterilmektedir.
using System;
public struct Number
{
private int n;
public Number(int value)
{
n = value;
}
public int Value
{
get { return n; }
}
public override bool Equals(Object obj)
{
if (obj == null || ! (obj is Number))
return false;
else
return n == ((Number) obj).n;
}
public override int GetHashCode()
{
return n;
}
public override string ToString()
{
return n.ToString();
}
}
public class Example1
{
public static void Main()
{
Random rnd = new Random();
for (int ctr = 0; ctr <= 9; ctr++) {
int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
Number n = new Number(randomN);
Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
}
}
}
// The example displays output like the following:
// n = -634398368, hash code = -634398368
// n = 2136747730, hash code = 2136747730
// n = -1973417279, hash code = -1973417279
// n = 1101478715, hash code = 1101478715
// n = 2078057429, hash code = 2078057429
// n = -334489950, hash code = -334489950
// n = -68958230, hash code = -68958230
// n = -379951485, hash code = -379951485
// n = -31553685, hash code = -31553685
// n = 2105429592, hash code = 2105429592
open System
[<Struct; CustomEquality; NoComparison>]
type Number(value: int) =
member _.Value = value
override _.Equals(obj) =
match obj with
| :? Number as n ->
n.Value = value
| _ -> false
override _.GetHashCode() =
value
override _.ToString() =
string value
let rnd = Random()
for _ = 0 to 9 do
let randomN = rnd.Next(Int32.MinValue, Int32.MaxValue)
let n = Number randomN
printfn $"n = {n,12}, hash code = {n.GetHashCode(),12}"
// The example displays output like the following:
// n = -634398368, hash code = -634398368
// n = 2136747730, hash code = 2136747730
// n = -1973417279, hash code = -1973417279
// n = 1101478715, hash code = 1101478715
// n = 2078057429, hash code = 2078057429
// n = -334489950, hash code = -334489950
// n = -68958230, hash code = -68958230
// n = -379951485, hash code = -379951485
// n = -31553685, hash code = -31553685
// n = 2105429592, hash code = 2105429592
Public Structure Number
Private n As Integer
Public Sub New(value As Integer)
n = value
End Sub
Public ReadOnly Property Value As Integer
Get
Return n
End Get
End Property
Public Overrides Function Equals(obj As Object) As Boolean
If obj Is Nothing OrElse Not TypeOf obj Is Number Then
Return False
Else
Return n = CType(obj, Number).n
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return n
End Function
Public Overrides Function ToString() As String
Return n.ToString()
End Function
End Structure
Module Example1
Public Sub Main()
Dim rnd As New Random()
For ctr As Integer = 0 To 9
Dim randomN As Integer = rnd.Next(Int32.MinValue, Int32.MaxValue)
Dim n As New Number(randomN)
Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode())
Next
End Sub
End Module
' The example displays output like the following:
' n = -634398368, hash code = -634398368
' n = 2136747730, hash code = 2136747730
' n = -1973417279, hash code = -1973417279
' n = 1101478715, hash code = 1101478715
' n = 2078057429, hash code = 2078057429
' n = -334489950, hash code = -334489950
' n = -68958230, hash code = -68958230
' n = -379951485, hash code = -379951485
' n = -31553685, hash code = -31553685
' n = 2105429592, hash code = 2105429592
Bir tür genellikle karma kodunun oluşturulmasına katılan birden çok veri alanına sahiptir. Karma kod oluşturmanın bir yolu, aşağıdaki örnekte gösterildiği gibi bu alanları bir XOR (eXclusive OR) işlem kullanarak birleştirmektir.
using System;
// A type that represents a 2-D point.
public struct Point2
{
private int x;
private int y;
public Point2(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(Object obj)
{
if (! (obj is Point2)) return false;
Point2 p = (Point2) obj;
return x == p.x & y == p.y;
}
public override int GetHashCode()
{
return x ^ y;
}
}
public class Example3
{
public static void Main()
{
Point2 pt = new Point2(5, 8);
Console.WriteLine(pt.GetHashCode());
pt = new Point2(8, 5);
Console.WriteLine(pt.GetHashCode());
}
}
// The example displays the following output:
// 13
// 13
// A type that represents a 2-D point.
[<Struct; CustomEquality; NoComparison>]
type Point(x: int, y: int) =
member _.X = x
member _.Y = y
override _.Equals(obj) =
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
x ^^^ y
let pt = Point(5, 8)
printfn $"{pt.GetHashCode()}"
let pt2 = Point(8, 5)
printfn $"{pt2.GetHashCode()}"
// The example displays the following output:
// 13
// 13
' A type that represents a 2-D point.
Public Structure Point3
Private x As Integer
Private y As Integer
Public Sub New(x As Integer, y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
If Not TypeOf obj Is Point3 Then Return False
Dim p As Point3 = CType(obj, Point3)
Return x = p.x And y = p.y
End Function
Public Overrides Function GetHashCode() As Integer
Return x Xor y
End Function
End Structure
Public Module Example3
Public Sub Main()
Dim pt As New Point3(5, 8)
Console.WriteLine(pt.GetHashCode())
pt = New Point3(8, 5)
Console.WriteLine(pt.GetHashCode())
End Sub
End Module
Önceki örnek (n1, n2) ve (n2, n1) için aynı karma kodu döndürür ve bu nedenle istenenden daha fazla çakışma oluşturabilir. .NET 5+ üzerinde, önerilen çözüm kullanmaktır HashCode.Combine. Simetri sorununu önler ve bir Tuple nesnesi oluşturmadan, iyi dağıtılmış bir hash kodu üretir.
using System;
public struct Point3
{
private int x;
private int y;
public Point3(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(Object obj)
{
if (obj is Point3)
{
Point3 p = (Point3) obj;
return x == p.x & y == p.y;
}
else
{
return false;
}
}
public override int GetHashCode()
{
return HashCode.Combine(x, y);
}
}
public class Example
{
public static void Main()
{
Point3 pt = new Point3(5, 8);
Console.WriteLine(pt.GetHashCode());
pt = new Point3(8, 5);
Console.WriteLine(pt.GetHashCode());
}
}
// The example displays output similar to the following.
// Note: HashCode.Combine results are not stable across .NET versions.
// 185727722
// -363254492
[<Struct; CustomEquality; NoComparison>]
type Point(x: int, y: int) =
member _.X = x
member _.Y = y
override _.Equals(obj) =
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
System.HashCode.Combine(x, y)
let pt = Point(5, 8)
printfn $"{pt.GetHashCode()}"
let pt2 = Point(8, 5)
printfn $"{pt2.GetHashCode()}"
// The example displays output similar to the following.
// Note: HashCode.Combine results are not stable across .NET versions.
// 185727722
// -363254492
Public Structure Point
Private x As Integer
Private y As Integer
Public Sub New(x As Integer, y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
If Not TypeOf obj Is Point Then Return False
Dim p As Point = CType(obj, Point)
Return x = p.x And y = p.y
End Function
Public Overrides Function GetHashCode() As Integer
Return HashCode.Combine(x, y)
End Function
End Structure
Public Module Example
Public Sub Main()
Dim pt As New Point(5, 8)
Console.WriteLine(pt.GetHashCode())
pt = New Point(8, 5)
Console.WriteLine(pt.GetHashCode())
End Sub
End Module
' The example displays output similar to the following.
' Note: HashCode.Combine results are not stable across .NET versions.
' 185727722
' -363254492
Açıklamalar
GetHashCode yöntemi, nesne eşitliği için hızlı denetimler gerektiren algoritmalar için bir karma kod sağlar. Karma kod, Dictionary<TKey,TValue> sınıfı, Hashtable sınıfı veya DictionaryBase sınıfından türetilmiş bir tür gibi, karma tabanlı bir koleksiyona nesne eklemek ve tanımlamak için kullanılan sayısal bir değerdir.
Note
Karma kodların karma tablolarda nasıl kullanıldığı hakkında bilgi edinmek ve bazı ek karma kod algoritmaları için Wikipedia'daki Karma İşlevi girdisine bakın.
Birbirine eşit olan iki nesne, eşit karma kodları döndürür. Ancak, tersi doğru değildir: eşit karma kodları nesne eşitliği anlamına gelmez, çünkü farklı (eşit olmayan) nesneler aynı karma kodlara sahip olabilir. Ayrıca, .NET GetHashCode yönteminin varsayılan uygulamasını garanti etmez ve bu yöntemin döndürdüğü değer, 32 bit ile 64 bit platformlar gibi .NET uygulamalar ve platformlar arasında farklılık gösterebilir. Bu nedenlerden dolayı, karma oluşturma amacıyla bu yöntemin varsayılan uygulamasını benzersiz bir nesne tanımlayıcısı olarak kullanmayın. Bundan iki sonuç çıkar:
- Eşit karma kodlarının nesne eşitliği anlamına geldiğini varsaymamalısınız.
- Hash kodunu oluşturulduğu uygulama etki alanı dışında asla kalıcı hale getirmemeli veya kullanmamalısınız, çünkü aynı nesne uygulama etki alanları, süreçler ve platformlar arasında farklı sonuçlar verebilir.
Warning
Karma kod, karma tabloyu temel alan koleksiyonlarda verimli ekleme ve arama için tasarlanmıştır. Karma kod kalıcı bir değer değildir. Bu nedenle:
- Karma kod değerlerini seri hale getirmeyin veya veritabanlarında depolamayın.
- Anahtarlı bir koleksiyondan nesne almak için karma kodu anahtar olarak kullanmayın.
- Karma kodları uygulama etki alanları veya işlemler arasında göndermeyin. Bazı durumlarda, hash kodları her bir işlem veya uygulama etki alanı bazında hesaplanabilir.
- Şifreleme açısından güçlü bir karmaya ihtiyacınız varsa, şifreleme karma işlevi tarafından döndürülen bir değer yerine karma kodu kullanmayın. Şifreleme karmaları için, System.Security.Cryptography.HashAlgorithm veya System.Security.Cryptography.KeyedHashAlgorithm sınıfından türetilmiş bir sınıf kullanın.
- İki nesnenin eşit olup olmadığını belirlemek için karma kodların eşitliğini test etmeyin. (False olan nesneler aynı hash kodlarına sahip olabilir.) Eşitliği test etmek için ReferenceEquals veya Equals yöntemini çağırın.
Yöntem GetHashCode türetilmiş bir tür tarafından geçersiz kılınabilir.
GetHashCode Geçersiz kılınmazsa, referans türleri için hash kodları, bir nesnenin referansına göre bir hash kodu hesaplayan temel sınıfın Object.GetHashCode yöntemi çağrılarak hesaplanır; daha fazla bilgi için bkz. RuntimeHelpers.GetHashCode. Başka bir deyişle, yönteminin döndürdüğü ReferenceEqualstrue iki nesne aynı karma kodlara sahiptir. Değer türleri GetHashCode ve ValueType.GetHashCode yöntemini geçersiz kılmıyorsa, temel sınıfın yöntemi, türün alanlarının değerlerine dayanarak karma kodunu hesaplamak için yansıma kullanır. Başka bir deyişle, alanları eşit değerlere sahip olan değer türleri eşit karma kodlara sahiptir. geçersiz kılma GetHashCodehakkında daha fazla bilgi için "Devralanlara Notlar" bölümüne bakın.
Warning
Eğer GetHashCode yöntemini geçersiz kılarsanız, Equals yöntemini de geçersiz kılmanız gerekir ve bunun tersi de geçerlidir. Geçersiz kılınan Equals yönteminiz iki nesne eşitlik için test edildiğinde döndürülüyorsa true , geçersiz kılınan GetHashCode yönteminiz iki nesne için aynı değeri döndürmelidir.
Eğer karma tablosunda anahtar olarak kullanılan bir nesne, GetHashCode'ın kullanışlı bir uygulamasını sağlamıyorsa, sınıf oluşturucusunun IEqualityComparer aşırı yüklemelerinden birine bir Hashtable hash kodu sağlayıcısı uygulaması vererek belirtebilirsiniz.
Devralanlara Notlar
Karma işlevi, bir nesnenin değerine karşılık gelen bir sayıyı (karma kodu) hızla oluşturmak için kullanılır. Karma işlevler genellikle her türe özeldir ve benzersizlik için giriş olarak örnek alanlarından en az birini kullanmalıdır. Karma kodlar statik alanların değerleri kullanılarak hesaplanmamalıdır.
öğesinden ObjectGetHashCode türetilen sınıflar için yöntemi yalnızca türetilmiş sınıf, başvuru eşitliği olarak eşitlik tanımlarsa temel sınıf GetHashCode() uygulamasına temsilci atayabilir. başvuru türleri için varsayılan uygulaması GetHashCode() , yöntemi tarafından GetHashCode(Object) döndürülene eşdeğer bir karma kodu döndürür. Sabit başvuru türleri için geçersiz kılabilirsiniz GetHashCode() . Genel olarak, değiştirilebilir başvuru türleri için yalnızca şu durumlarda geçersiz kılmalısınız GetHashCode() :
Karma kodu, değiştirilebilir olmayan alanlardan hesaplayabilirsiniz; Veya
Nesne karma kodunu kullanan bir koleksiyonda yer alırken, değiştirilebilir bir nesnenin karma kodunun değişmediğinden emin olabilirsiniz.
Aksi takdirde, karma tabloda değiştirilebilir nesnenin kaybolduğunu düşünebilirsiniz. Değiştirilebilir başvuru türü için geçersiz kılmayı GetHashCode() seçerseniz, belgeleriniz nesne karma tabloda depolanırken sizin türünüzün kullanıcılarının nesne değerlerini değiştirmemesi gerektiğini açıkça belirtmelidir.
Değer türleri için yansıma GetHashCode() kullanan bir varsayılan karma kod uygulaması sağlar. Daha iyi performans için geçersiz kılmayı düşünmelisiniz.
Karma kodları çeşitli yollarla hesaplayan daha fazla bilgi ve örnek için Örnekler bölümüne bakın.
Karma işlevi aşağıdaki özelliklere sahip olmalıdır:
İki nesne eşit olarak karşılaştırırsa, her nesnenin GetHashCode() yöntemi aynı değeri döndürmelidir. Ancak, iki nesne eşit olarak karşılaştırılmazsa, GetHashCode() iki nesnenin yöntemlerinin farklı değerler döndürmesi gerekmez.
GetHashCode() Bir nesnenin yöntemi, nesnenin System.Object.Equals yönteminin dönüş değerini belirleyen nesne durumunda değişiklik yapılmaması durumunda tutarlı olarak aynı karma kodu döndürmelidir. Bunun yalnızca bir uygulamanın geçerli yürütmesi için geçerli olduğunu ve uygulama yeniden çalıştırılırsa farklı bir karma kodun döndürülebileceğini unutmayın.
En iyi performans için karma işlevi, yoğun kümelenmiş giriş de dahil olmak üzere tüm girişler için eşit bir dağıtım oluşturmalıdır. Bunun bir etkisi, nesne durumunda yapılan küçük değişikliklerin en iyi karma tablo performansı için sonuçta elde edilen karma kodda büyük değişikliklere neden olmasıdır.
Karma işlevleri işlem için ucuz olmalıdır.
GetHashCode() yöntemi özel durumlar oluşturmamalıdır.
Örneğin, sınıfı tarafından GetHashCode() sağlanan yönteminin String uygulanması, aynı dize değerleri için aynı karma kodları döndürür. Bu nedenle, aynı dize değerini temsil eden iki String nesne aynı karma kodu döndürür. Ayrıca, giriş belirli aralıklarda kümelenmiş olsa bile yöntem dizedeki tüm karakterleri kullanarak makul bir şekilde rastgele dağıtılmış çıkış oluşturur (örneğin, bir dize 65.535 Unicode karakterden herhangi birini içerebilse bile, birçok kullanıcının yalnızca daha düşük 128 ASCII karakter içeren dizeleri olabilir).
Bir sınıfta iyi bir karma işlevi sağlamak, bu nesneleri karma tablosuna ekleme performansını önemli ölçüde etkileyebilir. Karma işlevinin iyi bir şekilde uygulanmasını sağlayan anahtarlara sahip karma tabloda, öğe aramak sabit zaman alır (örneğin, O(1) işlemi). Karma işlevinin kötü bir uygulamasına sahip karma tabloda, aramanın performansı karma tablodaki öğelerin sayısına (örneğin, karma tablosundaki öğelerin sayısı olan n bir O(n) işlemi) bağlıdır. Kötü amaçlı bir kullanıcı, aşağıdaki koşullar altında karma tablolara bağımlı uygulamaların performansını önemli ölçüde düşürebilen çakışma sayısını artıran veriler giriş yapabilir:
Karma işlevleri sık sık çakışmalar oluşturduğunda.
Karma tablodaki nesnelerin büyük bir kısmı birbirine eşit veya birbirine yaklaşık olarak eşit karma kodları oluşturduğunda.
Kullanıcılar karma kodun hesaplandığı verileri girdiklerinden.
Geçersiz kılan GetHashCode() türetilmiş sınıfların, eşit olarak kabul edilen iki nesnenin aynı karma koda sahip olmasını sağlamak için de geçersiz kılması Equals(Object) gerekir; aksi takdirde, Hashtable tür düzgün çalışmayabilir.