Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
== (eşitlik) ve != (eşitsizlik) işleçleri, işlenenlerinin eşit olup olmadığını denetler. İçerikleri eşit olduğunda değer türleri eşittir. İki değişken aynı depolama alanına başvurduğunda başvuru türleri eşittir.
C# dili başvuru belgesi, C# dilinin en son yayımlanan sürümünü gösterir. Ayrıca, yaklaşan dil sürümü için genel önizlemelerdeki özelliklere yönelik ilk belgeleri içerir.
Belgelerde ilk olarak dilin son üç sürümünde veya geçerli genel önizlemelerde sunulan tüm özellikler tanımlanır.
Tavsiye
Bir özelliğin C# dilinde ilk tanıtıldığı zamanları bulmak için C# dil sürümü geçmişi makalesine bakın.
is
== karşı test ederken bir teste alternatif olarak desen eşleştirme işlecini kullanabilirsiniz.
is işleci tüm değer ve başvuru türleri için varsayılan eşitlik semantiğini kullanır.
Eşitlik işleci ==
Eşitlik işleci==, işlenenleri eşitse, true aksi takdirde döndürürfalse.
Değer türleri eşitliği
Yerleşik değer türlerinin işlenenleri, değerleri eşitse eşittir:
int a = 1 + 2 + 3;
int b = 6;
Console.WriteLine(a == b); // output: True
char c1 = 'a';
char c2 = 'A';
Console.WriteLine(c1 == c2); // output: False
Console.WriteLine(c1 == char.ToLower(c2)); // output: True
Not
İşlenenlerden == işleçleri için işlemin sonucu olur<.><=>= Bu koşul, değerin NaN dahil olmak üzere doublediğer float (veya ) değerlerden büyük, küçük veya NaNbuna eşit olmadığı anlamına gelir. Daha fazla bilgi ve örnek için veya Double.NaN başvuru makalesine Single.NaN bakın.
Temel alınan tam sayı türünün karşılık gelen değerleri eşitse, aynı sabit listesi türünün iki işleneni eşittir.
Kullanıcı tanımlı yapı türleri varsayılan olarak işleci desteklemez == . İşleci == desteklemek için kullanıcı tanımlı bir yapıyı aşırı yüklemesi gerekir.
C# tanımlama kümeleri ve == için yerleşik desteğe != sahiptir. Daha fazla bilgi için, Tanımlama grubu türleri makalesinin Tanımlama Grubu eşitliği bölümüne bakın.
Başvuru türleri eşitliği
Varsayılan olarak, kayıtlar hariç başvuru türü işlenenler aynı nesneye başvuruda bulunurlarsa eşittir:
public class ReferenceTypesEquality
{
public class MyClass
{
private int id;
public MyClass(int id) => this.id = id;
}
public static void Main()
{
var a = new MyClass(1);
var b = new MyClass(1);
var c = a;
Console.WriteLine(a == b); // output: False
Console.WriteLine(a == c); // output: True
}
}
Yukarıdaki örnekte gösterildiği gibi, kullanıcı tanımlı başvuru türleri varsayılan olarak işleci destekler == . Ancak, bir başvuru türü işleci aşırı == yükleyebilir. Bir başvuru türü işleci aşırı yüklerse == , bu türdeki iki başvurunun Object.ReferenceEquals aynı nesneye başvurup başvurmadığını denetlemek için yöntemini kullanın.
Kayıt türleri eşitliği
Kayıt türleri, varsayılan olarak değer eşitliği semantiği sağlayan ve == işleçlerini destekler!=. Diğer bir ifadeyle, her ikisi de null tüm alanların değerleri veya bunlara karşılık gelen değerler olduğunda ve otomatik olarak uygulanan özellikler eşit olduğunda iki kayıt işleneni eşittir.
public class RecordTypesEquality
{
public record Point(int X, int Y, string Name);
public record TaggedNumber(int Number, List<string> Tags);
public static void Main()
{
var p1 = new Point(2, 3, "A");
var p2 = new Point(1, 3, "B");
var p3 = new Point(2, 3, "A");
Console.WriteLine(p1 == p2); // output: False
Console.WriteLine(p1 == p3); // output: True
var n1 = new TaggedNumber(2, new List<string>() { "A" });
var n2 = new TaggedNumber(2, new List<string>() { "A" });
Console.WriteLine(n1 == n2); // output: False
}
}
Yukarıdaki örnekte gösterildiği gibi, başvuru türü üyelerinin eşitliği kendi eşitlik uygulamaları kullanılarak karşılaştırılır.
Dize eşitliği
her ikisi de aynı uzunlukta olduğunda veya her iki dizenulldize işleneni eşittir:
string s1 = "hello!";
string s2 = "HeLLo!";
Console.WriteLine(s1 == s2.ToLower()); // output: True
string s3 = "Hello!";
Console.WriteLine(s1 == s3); // output: False
Dize eşitliği karşılaştırmaları büyük/küçük harfe duyarlı sıralı karşılaştırmalardır. Dize karşılaştırması hakkında daha fazla bilgi için bkz . C# dilinde dizeleri karşılaştırma.
Temsilci eşitliği
Her ikisi de aynı uzunlukta olduğunda ve her konumda eşit girişlere sahip olduğunda, aynı çalışma zamanı türündeki iki null işlenen eşittir:
Action a = () => Console.WriteLine("a");
Action b = a + a;
Action c = a + a;
Console.WriteLine(object.ReferenceEquals(b, c)); // output: False
Console.WriteLine(b == c); // output: True
Önemli
Çağırma listesindeki eşit girdiler, alıcı dahil olmak üzere çağrıdaki tüm sabit parametreleri içerir. Alıcı, girdi çağrıldığında tarafından this temsil edilen bir nesnenin örneğidir.
var o1 = new object();
var o2 = new object();
var d1 = o1.ToString;
var d2 = o2.ToString;
Console.WriteLine(object.ReferenceEquals(d1, d2)); // output: False
Console.WriteLine(d1 == d2); // output: False (different receivers)
Daha fazla bilgi için C# dil belirtiminin Temsilci eşitlik işleçleri bölümüne bakın.
Aşağıdaki örnekte gösterildiği gibi, anlamsal olarak özdeş lambda ifadelerini değerlendirmeden gelen temsilciler eşit değildir:
Action a = () => Console.WriteLine("a");
Action b = () => Console.WriteLine("a");
Console.WriteLine(a == b); // output: False
Console.WriteLine(a + b == a + b); // output: True
Console.WriteLine(b + a == a + b); // output: False
Eşitsizlik işleci !=
Eşitsizlik işleci!=, işlenenleri eşit değilse ve true değilse döndürürfalse. Yerleşik türlerin işlenenleri için ifadex != y, ifadesiyle !(x == y)aynı sonucu verir. Tür eşitliği hakkında daha fazla bilgi için Eşitlik işleci bölümüne bakın.
Aşağıdaki örnekte işlecinin nasıl kullanılacağı gösterilmektedir != :
int a = 1 + 1 + 2 + 3;
int b = 6;
Console.WriteLine(a != b); // output: True
string s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(s1 != s2); // output: False
object o1 = 1;
object o2 = 1;
Console.WriteLine(o1 != o2); // output: True
Sınıf hiyerarşilerinde eşitlik
Kayıtlar el ile çalışma olmadan devralmayı doğru işler. Derleyici tarafından oluşturulan eşitlik hem çalışma zamanı türünü hem de bildirilen tüm özellikleri denetler, böylece simetri ve geçiş gereksinimlerini otomatik olarak karşılar. Amaç değer eşitliği olduğunda el ile korumasız hiyerarşiyi tercih record edin.
Önemli
Mümkün olduğunda kullanın record ; derleyici sizin için gerekli tüm eşitlik üyelerini oluşturur. El ile uygulama yalnızca türünüzün kayıt dışı bir sınıftan türetilmesi gerektiğinde veya engelleyen recordbaşka kısıtlamaları olduğunda gereklidir.
Bir tür kayıt türü olamadığında eşitliği kendiniz tanımlayın
Aşağıda, kayıt olmayan bir değer türü için el ile gerçekleştirilen en düşük uygulama aşağıdadır:
class Color : IEquatable<Color>
{
public Color(int r, int g, int b)
{
R = r;
G = g;
B = b;
}
public int R { get; }
public int G { get; }
public int B { get; }
public bool Equals(Color? other) =>
other is not null && R == other.R && G == other.G && B == other.B;
public override bool Equals(object? obj) => obj is Color other && Equals(other);
public override int GetHashCode() => HashCode.Combine(R, G, B);
}
Uygulama üç gerekli üye sağlar: Equals(T?) çekirdek karşılaştırması olarak, override Equals(object?) nesne düzeyi çağrıları için ve override GetHashCode() karma tabanlı koleksiyonlar düzgün çalışır.
HashCode.Combine , tarafından Equalskullanılan değerlerden bir karma oluşturan bir kitaplık yardımcısıdır.
IEquatable<T> Uygulama (Equals(T?)aşırı yükleme) isteğe bağlıdır, ancak arayanlar zaten somut türe sahip olduğunda kutulamadan kaçınır.
ve !=öğesini de tanımladığınızda==, dil çift olarak gerektirir; CS0660 ve CS0661 uyarıları dört üyenin de tutarlı kalmasını anımsatır.
Yukarıdaki üç üye olduğu için değer Equals eşitliğini yansıtır, ancak == henüz hiçbir == işleç bildirilmemiş olduğundan kimliği test eder:
var red1 = new Color(255, 0, 0);
var red2 = new Color(255, 0, 0);
Console.WriteLine(red1.Equals(red2)); // => True
Console.WriteLine(red1 == red2); // => False (no == overload; identity check)
Doğru bir uygulamanın denklik sözleşmesini de karşılaması gerekir (, yve z değerlerinin null olmadığını varsayalımx):
-
Esnek:
x.Equals(x)döndürürtrue. -
Simetrik:
x.Equals(y)ile aynı değeriy.Equals(x)döndürür. -
Geçişli: ve
y.Equals(z)her ikisi detrueisex.Equals(y), olmalıdırx.Equals(z)true. -
Tutarlı: nesne değişmediği sürece aynı değeri döndürmek için
x.Equals(y)ardışık çağrılar. -
Null davranış:
x.Equals(null)döndürürfalse;x.Equals(y)nullxolmayan bir üzerinde çağrıldığında oluşturmamalıdır.
Korumasız bir sınıf hiyerarşisindeki değer eşitliği, simetrik ve geçişli kuralları karşılamak için korumalı bir sınıftan daha fazla özen gerektirir. Tehlike, gönderimin IEquatable<T>.Equals(T? other) çalışma zamanı türünü değil değişkenin bildirilen türünü (değişken bildiriminde yazılan tür) takip etmesidir. OlmayanvirtualEquals(Shape? other) bir bildirirseShape, çalışma zamanında tutan olarak Shape yazılan bir Circle değişken çağrılır Shape.Equalsve özel alanları sessizce yoksayılırCircle. Farklı yarıçaplara sahip iki Circle nesne, bir Shape değişken üzerinden erişildiğinde eşit olarak karşılaştırılabilir.
Doğru desen iki işbirliği gereksinimi gerektirir: türetilmiş her sınıfın karşılaştırmayı genişletebilmesi için türetilmiş Equals yöntemi virtual oluşturun ve farklı çalışma zamanı türlerindeki nesnelerin hiçbir zaman eşit kabul edilmemesi için temel sınıf uygulamasına bir GetType() == other.GetType() koruma ekleyin.
Temel sınıf uygulaması
// Shape is an unsealed base class. Making Equals virtual and guarding with GetType()
// ensures a derived instance is never equal to an instance of a different runtime type.
class Shape : IEquatable<Shape>
{
public string Color { get; }
public Shape(string color) => Color = color;
public override bool Equals(object? obj) => Equals(obj as Shape);
// virtual so derived classes can override and augment the comparison
public virtual bool Equals(Shape? other) =>
other is not null &&
GetType() == other.GetType() && // reject different runtime types
Color == other.Color;
// GetType() is included because equality requires matching runtime types
public override int GetHashCode() => HashCode.Combine(GetType(), Color);
public static bool operator ==(Shape? l, Shape? r) => l?.Equals(r) ?? r is null;
public static bool operator !=(Shape? l, Shape? r) => !(l == r);
}
Önemli noktalar:
-
virtualtypedEquals: Türetilen her sınıf, karşılaştırmayı kendi alanlarıyla artırmak için bu yöntemi geçersiz kılar. -
GetType()guard:GetType() == other.GetType()birCircleöğesinin aynı renge sahip birShapedeğerine eşitlenmesini engeller ve farklı türetilmiş türlerdeki nesnelerin birbirine eşit olmasını önler. -
GetHashCodeiçerirGetType(): çünkü iki nesne yalnızca çalışma zamanı türleri eşleştiğinde eşit olduğundan,GetHashCodeveri alanlarının yanı sıra çalışma zamanı türünü de karma olarak içermelidir. Burada atlanmasıGetType()veHashSet<T>içinde yanlış davranışaDictionary<TKey,TValue>neden olur. -
==için temsilcilerEqualsişleç ve yöntem eşitliğini tutarlı tutar.
Türetilmiş sınıf uygulaması
Alan ekleyen türetilmiş bir sınıf türü Equalsgeçersiz kılar, kendi türüne yayınlar, çağırır base.Equalsve sonra kendi alanlarını karşılaştırır:
class Circle : Shape
{
public double Radius { get; }
public Circle(string color, double radius) : base(color) => Radius = radius;
public override bool Equals(object? obj) => Equals(obj as Shape);
// Calls base.Equals to verify Color and runtime type, then adds Radius
public override bool Equals(Shape? other) =>
other is Circle c && base.Equals(c) && Radius == c.Radius;
public override int GetHashCode() => HashCode.Combine(GetType(), Color, Radius);
}
base.Equals(c) korumayı GetType() zorlar ve paylaşılan alanları denetler. bağımsız değişken başka türetilmiş bir Shape tür olduğunda aracılığıyla other is Circle c atama işlemi hızlı başarısız olur.
Temel tür değişkeni aracılığıyla kullanım
Shape circle1 = new Circle("red", 5.0);
Shape circle2 = new Circle("red", 7.0);
Shape circle3 = new Circle("red", 5.0);
Shape shape1 = new Shape("red");
Console.WriteLine(circle1.Equals(circle2)); // => False (Radius differs)
Console.WriteLine(circle1.Equals(circle3)); // => True
Console.WriteLine(circle1.Equals(shape1)); // => False (different runtime types)
Korumalı sınıflar daha basittir
Bir sınıfı alt sınıfa sealed ayıramazsınız, bu nedenle derleme zamanı ve çalışma zamanı türleri her zaman kabul eder. Görevliye GetType() veya virtual merkeze ihtiyacınız yok. Bir IEquatable<T>tür kayıt olamazken eşitliği kendiniz uygulama bölümünde gösterilen desen, korumalı bir sınıf için doğru ve eksiksizdir.
İşleç aşırı yüklenebilirliği
kullanıcı tanımlı bir türdeki ve işleçlerini ==!=. Bu iki işleçlerden birini aşırı yüklerseniz, diğer işleci de aşırı yüklemelisiniz.
Kayıt türündeki == ve != işleçlerini açıkça aşırı yükleyemezsiniz. kayıt türü için ve == işleçlerinin != davranışını değiştirmek için aşağıdaki imzayla yöntemini uygulayınT:IEquatable<T>.Equals
public virtual bool Equals(T? other);
C# dili belirtimi
Daha fazla bilgi için C# dil belirtiminin İlişkisel ve tür testi işleçleri bölümüne bakın.
Kayıt türlerinin eşitliği hakkında daha fazla bilgi için C# dil belirtimininEşitlik üyeleri bölümüne bakın.