| « button1_click | VS2005 Araçları » |
Equals ve ==
![]()
Kullandığınız objenin tipi ne olursa olsun .NET'de iki objenin eşit olup olmadığını karşılaştırmanın iki yolu vardır.
if ( a == b )
yada
if ( a.Equals(b) )
Görünüşte aynı işi yapıyor gibi olsalarda gerçekte oldukça farklıdırlar.
Follow up:
String gibi üzerinde oynanmış tipleri saymaz isek aslen == kontrolü iki değişkenin aynı memory adresini gösterip göstermediğini kontrol eder, Equals ise eşitlik kontrolü yapar.
Örneğin;
string a = "test";
string b = "test";
Console.WriteLine( "Sonuç 1: " + ( b == a ) );
Sonuç olarak True verirken,
string a = "test";
string b = "test";
object c = b;
Console.WriteLine( "Sonuç 1: " + ( c == a ) );
Console.WriteLine( "Sonuç 2: " + ( c.Equals(a) ) );
Sonuç 1 olarak False verirken Sonuç 2 için True verir.
Neden böyle bir fark var ?
Örneğin Kitap adında bir class'ımız ve üzerinde Baslik alanı bulunsun.
class Kitap
{
public Baslik;
}
Şimdi bu class'ımızda eşitlik kontrolü yaparken neyi kontrol etmemiz gerekli ? Mesela aynı adda iki kitabımız olduğunda mı yoksa aynı memory adresini gösteriyolar ise mi aynı olduklarına mı karar vermeliyiz. Sorun burada başlıyor.
Temel kullanım olarak Equals metodu öncelikle memory adresi kontrolünü yapar ve farklılık varsa class içerisindeki değerleri kontrol etmelidir.
Yani aynı adda iki kitabı karşılaştırırken Equals metodu True vermelidir. Ancak == operatörü kullanırken kitaplar aynı adda olsa bile aynı memory adresini işaret etmiyorlarsa işlemin sonucu False olmalıdır.
Böylece aynı memory adresini göstermek mi, eşitlik kontrolümü yapılacağı ayrılmış olur.
Referans tipinde tanımlanmış classlar üzerinde çok özel durumlar haricinde == operatörü için herhangi bir şey yapmanıza genellikle gerek yoktur. Basitçe memory adresi kontrolü nerdeyse tüm tipler için geçerlidir.
Immutable Tipler
Ancak içeriği sabit,değiştirilmeyen ve genelliklede kısa bir hayatı olan tiplere verilen isimle Immutable tiplerde == operatörünü tekrar bir ele almak gerekebilir.
Örneğin string buna bir örnektir. .Net'de string'leri yanlızca ve yanlızca 1 kez yaratırsınız ve üzerinde değişiklik yapamazsınız. (Bkz: string.Intern) Örneğin;
string a = "test";
a[1] = 'o';
şeklindeki bir ifade derlenmeyecektir. Bu tür bir kullanım gerekiyorsa StringBuilder kullanılmalıdır.
Hatta kod içerisinde;
string a = "test";
string b = "test";
kullanıldığında a ve b değişkenleri aynı memory adresini kullanacaklardır. İki string'i birleştirerek yeni bir string üretmeniz durumunda dahi eski string'ler çöpe atılır ve yeni bir string değişkeni üretilir.
Bu tipde bir class'ınız var ise == operatörünü düzenleyerek içerik kontrolü yapmasını sağlamak isteyebilirsiniz. Aksi halde if bloklarınızda garip gelebilecek hatalarla karşılaşabilirsiniz.
Equals
Bir nesnenin diğerine eşit olup olmadığını kesin olarak anlayabileceğiniz en iyi yer bu metoddur. Ancak "object" üzerindeki Equals metodu pek fazla bir iş yapmadığından bu metodu kendinize göre düzenlemek isteyebilirsiniz ve tasarımcılar buna izin vermek için Equals metodunu virtual olarak tanımlamışlardır.
Böylece;
public override bool Equals(object other)
{
if ( !object.ReferenceEquals(this,other) )
if ( other.GetType() == this.GetType() )
return Equals((Kitap)other);
return false;
}
public bool Equals(Kitap other)
{
if ( object.ReferenceEquals(other,this) )
return true;
return this.Baslik.Equals(other.Baslik);
}
şeklinde (biraz kalabalıkta olsa) içerik kontrolü yapmanız mümkündür.
object.ReferenceEquals() metodu aynı memory adresini gösterdiklerini kontrol etmek için kullanılmıştır.
Value Type
Referans tipi classlardan farklı olarak Value Type class'larda (struct) == operatörü memory adresi kontrolünün yanında üzerindeki alanları Reflection kullanarak eşit olup olmadıkları kontrolünü yapar.
Örneğin;
Point p1 = new Point(50,50);
Point p2 = new Point(50,50);
Console.WriteLine( p1 == p2 );
Biraz yavaş olsada bu tür class'ların mantığına uygun olarak emin olmanın en iyi yolu budur.
Özet
Kullandığınız class'larda memory adresimi mi yoksa eşitlik kontrolü mü yapacağınıza iyi karar vermeniz gereklidir. Memory adresi kontrolü hızlı olsada bazı durumlarda eşitlik kontrolü yapmanız gerekebilir.
Eşitlik kontrolleri için tanımladığınız class'larda Equals metodunu override etmek ilerdeki akıl sağlığınız için faydalı olacaktır.