Neden C # 'da == ve! = Tanımlamalıyız?


346

C # derleyicisi, özel bir tür operatörü tanımladığında ==, bunu tanımlaması gerektiğini de gerektirir !=( buraya bakın ).

Neden?

Tasarımcıların neden gerekli olduğunu düşündüklerini merak ediyorum ve derleyici neden sadece diğeri mevcut olduğunda operatörlerden herhangi biri için makul bir uygulamaya geçemiyor. Örneğin, Lua sadece eşitlik operatörünü tanımlamanızı sağlar ve diğerini bedavaya alırsınız. C # aynı şeyi == ya da hem == ve! = Tanımlamanızı ve ardından otomatik olarak eksik! = İşlecini derlemenizi isteyebilir !(left == right).

Bazı varlıkların eşit veya eşit olmayan (IEEE-754 NaN'ler gibi) olabileceği garip köşe vakaları olduğunu anlıyorum, ancak bunlar kural değil istisna gibi görünüyor. Yani bu, C # derleyici tasarımcılarının istisnayı neden kural haline getirdiğini açıklamıyor.

Eşitlik operatörünün tanımlandığı zayıf işçilik vakaları gördüm, o zaman eşitsizlik operatörü, her karşılaştırmanın tersine çevrildiği ve her && bir || (noktayı anlıyorsunuz ... temel olarak! (a == b) De Morgan'ın kuralları ile genişledi). Bu, derleyicinin Lua'da olduğu gibi tasarımla ortadan kaldırabileceği zayıf bir uygulamadır.

Not: Aynısı <> <=> = operatörleri için de geçerlidir. Bunları doğal olmayan yollarla tanımlamanız gereken vakaları hayal edemiyorum. Lua sadece <ve <= tanımlamanıza ve> = ve> doğal olarak şekillendiricilerin olumsuzlaması yoluyla tanımlamanıza izin verir. Neden C # aynı şeyi yapmıyor (en azından 'varsayılan olarak')?

DÜZENLE

Görünüşe göre programcının istedikleri gibi eşitlik ve eşitsizlik kontrolleri yapmasına izin vermek için geçerli nedenler var. Cevapların bazıları bunun güzel olabileceği durumlara işaret ediyor.

Ancak sorumun çekirdeği, bu genellikle mantıksal olarak gerekli olmadığında neden C # 'da zorla gerekli?

Bu NET arayüzleri benzeri için seçimler tasarlamak için çarpıcı aksine aynı zamanda Object.Equals, IEquatable.Equals IEqualityComparer.Equalsbir eksikliği nerede NotEqualsçerçevesi düşündüğü muadili gösterileri !Equals()eşitsiz olarak nesneleri ve bu. Ayrıca, sınıflar Dictionaryve benzeri yöntemler .Contains()sadece yukarıda bahsedilen arayüzlere bağlıdır ve tanımlanmış olsalar da operatörleri doğrudan kullanmazlar. ReSharper eşitlik üyelerini oluşturur Aslında, her iki tanımlar ==ve !=bakımından Equals()o zaman bile kullanıcı seçer hiç operatörleri üretmek için yalnızca ve. Eşitlik operatörlerine nesne eşitliğini anlamak için çerçeve gerekmemektedir.

Temel olarak, .NET çerçevesi bu operatörleri umursamıyor, sadece birkaç Equalsyöntemi önemsiyor . == ve! = İşleçlerinin kullanıcı tarafından birlikte tanımlanmasını isteme kararı, .NET ile ilgili olarak nesne semantiği ile değil, yalnızca dil tasarımıyla ilgilidir.


24
Mükemmel bir soru için +1. Hiç bir neden yok gibi görünüyor ... tabii ki derleyici aksi belirtilmedikçe! = B'nin! (A == b) diline çevrilebileceğini varsayabilir. Bunu da neden yapmaya karar verdiklerini merak ediyorum.
Patrick87

16
Bu, oylanan ve favorilere eklenen bir soruyu gördüğüm en hızlı şey.
Christopher Currens

26
Eminim @Eric Lippert de sağlam bir cevap verebilir.
Yuck

17
"Bilim adamı doğru cevapları veren biri değil, doğru soruları soran kişi". Bu yüzden SE'de sorular teşvik edilmektedir. Ve çalışıyor!
Adriano Carneiro

Yanıtlar:


161

Dil tasarımcıları için konuşamam, ama aklıma gelen şeyden, kasıtlı, uygun tasarım kararı gibi görünüyor.

Bu temel F # koduna bakarak, bunu çalışan bir kütüphaneye derleyebilirsiniz. Bu F # için yasal koddur ve eşitlik operatörünü aşırı yükler, eşitsizliği değil:

module Module1

type Foo() =
    let mutable myInternalValue = 0
    member this.Prop
        with get () = myInternalValue
        and set (value) = myInternalValue <- value

    static member op_Equality (left : Foo, right : Foo) = left.Prop = right.Prop
    //static member op_Inequality (left : Foo, right : Foo) = left.Prop <> right.Prop

Bu tam olarak neye benzediğini yapar. Yalnızca üzerinde bir eşitlik karşılaştırıcısı oluşturur ==ve sınıfın iç değerlerinin eşit olup olmadığını kontrol eder.

Eğer C # böyle bir sınıf oluşturmak edemesek de, sen yapabilirsiniz .NET için derlendi birini kullanın. Aşırı yüklenmiş operatörümüzü kullanacağı açıktır == Peki, çalışma zamanı ne için kullanıyor !=?

C # EMCA standardı, eşitliği değerlendirirken hangi operatörün kullanılacağını nasıl belirleyeceğini açıklayan bir dizi kurala (bölüm 14.9) sahiptir. Aşırı basitleştirilmiş ve böylece tam olarak doğru olmayan bir şekilde koymak için, karşılaştırılan türler aynı türdeyse ve aşırı yüklenmiş bir eşitlik operatörü varsa, bu aşırı yüklenmeyi kullanır ve Object'den miras alınan standart referans eşitlik operatörünü kullanmaz. O zaman, operatörlerden sadece biri mevcutsa, tüm referansların sahip olduğu varsayılan referans eşitlik operatörünü kullanması şaşırtıcı değildir. 1

Durumun böyle olduğunu bilerek, asıl soru şudur: Bu neden bu şekilde tasarlandı ve derleyici bunu neden kendi başına çözemedi? Birçok insan bunun bir tasarım kararı olmadığını söylüyor, ancak özellikle tüm nesnelerin varsayılan bir eşitlik operatörü olduğu gerçeğiyle ilgili olarak bu şekilde düşünüldüğünü düşünüyorum.

Peki, derleyici neden !=operatörü otomatik olarak oluşturmuyor ? Microsoft'tan biri bunu onaylamadığı sürece emin olamıyorum, ancak gerçekleri akıl yürütmeden belirleyebileceğim şey bu.


Beklenmedik davranışları önlemek için

Belki de ==eşitliği test etmek için bir değer karşılaştırması yapmak istiyorum . Bununla birlikte, !=referans eşit olmadığı sürece değerlerin eşit olup olmadığını hiç umursamadım, çünkü programımın eşit olduğunu düşünmek için sadece referansların eşleşmesi umurumda. Sonuçta, bu aslında C # 'ın varsayılan davranışı olarak özetlenmiştir (her iki operatör aşırı yüklenmemişse, başka bir dilde yazılmış bazı .net kütüphanelerinde olduğu gibi). Derleyici otomatik olarak kod ekliyordu, artık uyumlu olması gereken çıktı kodu için derleyiciye güvenemedim. Derleyici, özellikle yazdığınız kod hem C # hem de CLI standartları dahilinde olduğunda, davranışınızı değiştiren gizli kod yazmamalıdır.

Sizi aşırı yüklemeye zorlamak açısından , varsayılan davranışa gitmek yerine, sadece standart (EMCA-334 17.9.2) 2'de olduğunu söyleyebilirim . Standart nedenini belirtmez. Bu C # C ++ çok davranış ödünç gerçeği nedeniyle inanıyorum. Bununla ilgili daha fazla bilgi için aşağıya bakın.


Geçersiz kıldığınızda !=ve ==, bool döndürmeniz gerekmez.

Bu başka bir olası nedendir. C # 'da bu işlev:

public static int operator ==(MyClass a, MyClass b) { return 0; }

şu kadar geçerli:

public static bool operator ==(MyClass a, MyClass b) { return true; }

Bool dışında bir şey döndürüyorsanız, derleyici otomatik olarak zıt bir tür çıkaramaz . Ayrıca, operatörünüz durumunda yapar yukarıda da belirttiğim gibi dönüş bool, sadece kod, onları bu belirli bir durumda var sadece olurdu kodu oluşturmak oluşturmak için mantıklı veya etmediğini gizler CLR varsayılan davranış.


C # C ++ 3'ten çok ödünç alır

C # tanıtıldığında, MSDN dergisinde C # hakkında konuşan bir makale vardı:

Birçok geliştirici, Visual Basic gibi yazması, okunması ve bakımı kolay bir dil olmasını ister, ancak yine de C ++ 'ın gücünü ve esnekliğini sağlar.

Evet, C # için tasarım hedefi, C ++ ile neredeyse aynı miktarda güç vermekti ve katı tip güvenlik ve çöp toplama gibi kolaylıklar için sadece biraz fedakarlıktı. C #, C ++ 'dan sonra güçlü bir şekilde modellenmiştir.

Bu örnek programda gösterildiği gibi , C ++ 'da eşitlik işleçlerinin bool döndürmesi gerekmediğini öğrenmek sizi şaşırtmayabilir.

Şimdi, C ++ tamamlayıcı operatörü aşırı yüklemenizi gerektirmez . Kodu örnek programda derlediyseniz, kodun hatasız çalıştığını göreceksiniz. Ancak, satırı eklemeyi denediyseniz:

cout << (a != b);

Alacaksın

derleyici hatası C2678 (MSVC): ikili '! =': 'Test' türünün sol işlenenini alan bir operatör bulunamadı (ya da kabul edilebilir bir dönüşüm yok) `.

C ++ kendisi çiftler halinde aşırı gerektirmez iken yani, öyle olmaz Eğer özel bir sınıf üzerinde aşırı ilişkin ortada eşitlik operatörü kullanalım. .NET'te geçerlidir, çünkü tüm nesnelerin varsayılanı vardır; C ++ bunu yapmaz.


1. Bir yan not olarak, C # standardı, ikisinden birini aşırı yüklemek istiyorsanız hala operatör çiftini aşırı yüklemenizi gerektirir. Bu, sadece derleyicinin değil , standardın bir parçasıdır . Ancak, aynı gereksinimleri olmayan başka bir dilde yazılmış bir .net kütüphanesine erişirken hangi operatörün aranacağını belirlemeye ilişkin aynı kurallar.

2. EMCA-334 (pdf) ( http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf )

3. Ve Java, ama buradaki nokta bu değil


75
" Boole geri dönmek zorunda değilsiniz " .. Bence bu bizim cevabımız; aferin. ! (O1 == o2) iyi tanımlanmamışsa standardın ona güvenmesini bekleyemezsiniz.
Brian Gordon

10
İronik olarak, mantıksal işleçlerle ilgili bir konuda cümlenin içinde bir çift negatif kullandınız, "C #," C # 'dan mantıksal olarak "herhangi birinin yalnızca birini geçersiz kılmanıza izin verdiği anlamına gelir."
Dan Diplo

13
@Dan Diplo, Sorun değil, Bunu yapmamam yasak değil.
Christopher Currens

6
Doğruysa, # 2'nin doğru olduğundan şüpheleniyorum; ama şimdi soru, neden ==a dışında bir şey döndürmeye izin veriyor bool? An döndürürseniz int, artık koşullu bir ifade olarak kullanamazsınız. if(a == b)artık derlenmeyecek. Amaç ne?
BlueRaja - Danny Pflughoeft

2
Bool (örtülü doğru / yanlış) örtülü bir dönüştürme olan bir nesneyi döndürebilirsiniz ama yine de bunun yararlı olacağını göremiyorum.
Stefan Dragnev

53

Muhtemelen birisinin üç değerli mantık uygulaması gerekiyorsa (yani null). Bu gibi durumlarda - örneğin ANSI standart SQL - operatörler girdiye bağlı olarak basitçe reddedilemez.

Aşağıdaki durumlarda bir davaya sahip olabilirsiniz:

var a = SomeObject();

Ve a == truedöner falseve a == falsedöner false.


1
Bu durumda söyleyebilirim, abir boolean olmadığından, bunu gerçek trueya da değil, üç durumlu bir enum ile karşılaştırmalısınız false.
Brian Gordon

18
Bu arada, kimsenin FileNotFound şakasına başvurmadığına inanamıyorum ..
Brian Gordon

28
Eğer a == truebir falseo hep beklediğiniz a != trueolmaya truerağmen a == falsevarlıkfalse
Fede

20
@ Fede kafasına çiviyi vurdu. Bunun gerçekten soru ile ilgisi yok - birisinin neden geçersiz kılmak isteyebileceğini açıklıyorsunuz ==, neden ikisini de geçersiz kılmak zorunda kalmayacağını değil.
BlueRaja - Danny Pflughoeft

6
@Yuck - Evet, iyi bir varsayılan uygulama var: bu yaygın bir durumdur. Örneğinizde bile, varsayılan uygulaması !=doğru olacaktır. Gelen son derece biz istediğimiz nadir durumda x == yve x != yher iki be YANLıŞ olarak (ben mantıklı tek örnek düşünemiyorum) , hala varsayılan uygulama geçersiz kılmak ve kendi sağlayabilir. Her zaman ortak durumu varsayılan yapın!
BlueRaja - Danny Pflughoeft

25

Bunun dışında C # birçok alanda C ++ 'ı savunur, aklıma gelen en iyi açıklama bazı durumlarda "eşitlik" ispat etmekten biraz "eşitlik" ispatlamak için biraz farklı bir yaklaşım almak isteyebilirsiniz .

Örneğin, dize karşılaştırmasıyla, returneşleşmeyen karakterleri gördüğünüzde eşitliği ve döngü dışı olup olmadığını test edebilirsiniz . Ancak, daha karmaşık problemlerle o kadar temiz olmayabilir. Çiçeklenme filtre akla gelen; çok eleman ise hızla söylemek kolay değil elemanı olmadığını söylemek için sette, ama zor olduğu sette. Aynı returnteknik uygulanabilir olsa da , kod o kadar da güzel olmayabilir.


6
Harika bir örnek; Bence nedenini düşünüyorsun. Basit !bir bilgi, size bilgili bir kodlayıcının hem == ve hem de optimize edebileceği tek bir eşitlik tanımına kilitlenir !=.
Yuck

13
Bu yüzden neden onlara zorlanmaları gerektiğini değil ikisini de geçersiz kılma seçeneği verildiğini açıklıyor .
BlueRaja - Danny Pflughoeft

1
Bu bağlamda, her ikisini de optimize etmek zorunda değiller , sadece her ikisinin de net bir tanımını yapmak zorundalar .
Jesper

22

.Net kaynağında == ve! = Aşırı yük uygulamalarına bakarsanız, genellikle! = Olarak uygulanmazlar (left == right). Tamamen (= = gibi) negatif mantıkla uygularlar. Örneğin, DateTime == as

return d1.InternalTicks == d2.InternalTicks;

ve! = olduğu gibi

return d1.InternalTicks != d2.InternalTicks;

Siz (veya derleyici bunu örtük olarak yapmışsa)! = As

return !(d1==d2);

o zaman sınıfınızın referans aldığı şeylerde == ve! = dahili uygulaması hakkında bir varsayımda bulunuyorsunuz. Bu varsayımdan kaçınmak, kararlarının ardındaki felsefe olabilir.


17

Düzenlemenize cevap vermek için, her ikisini de geçersiz kılarsanız neden geçersiz kılmak zorunda kaldığınıza ilişkin olarak, hepsi mirastır.

== değerini geçersiz kılarsanız, büyük olasılıkla bir tür anlamsal veya yapısal eşitlik sağlamanız durumunda (örneğin, InternalTicks özellikleri farklı örnekler olsa bile eşitse DateTimes eşittir), o zaman operatörün varsayılan davranışını Tüm .NET nesnelerinin üstü olan nesne. == işleci, C # 'da, temel uygulaması Object.operator (==) bir başvuru karşılaştırması gerçekleştiren bir yöntemdir. Object.operator (! =), Referans karşılaştırması da yapan başka, farklı bir yöntemdir.

Metodun geçersiz kılmasının hemen hemen her başka durumunda, bir metodun geçersiz kılmasının aynı zamanda bir anormallik metodunda davranışsal bir değişikliğe yol açacağını varsaymak mantıksız olacaktır. Increment () ve Decrement () yöntemleriyle bir sınıf oluşturduysanız ve bir alt sınıfta Increment () yöntemini geçersiz kılarsanız, Decrement () öğesinin de geçersiz kılınan davranışınızın tersi ile geçersiz kılınmasını ister misiniz? Derleyici, olası tüm durumlarda bir operatörün herhangi bir uygulaması için ters fonksiyon oluşturacak kadar akıllı hale getirilemez.

Ancak, operatörler yöntemlere çok benzer şekilde uygulansa da, kavramsal olarak çiftler halinde çalışır; == ve! =, <ve> ve <= ve> =. Bu durumda, tüketicinin bakış açısından! = == 'dan farklı çalıştığını düşünmek mantıksız olurdu. Bu nedenle, derleyici her durumda! = B ==! (A == b) olduğunu varsaymak için yapılamaz, ancak genellikle == ve! = 'Nin benzer bir şekilde çalışması beklenir, bu nedenle derleyici zorlar çiftler halinde uygulayabilirsiniz, ancak aslında bunu yaparsınız. Sınıfınız için bir! = B ==! (A == b) ise, o zaman! (==) kullanarak! = Operatörünü uygulayın, ancak bu kural nesneniz için her durumda geçerli değilse (örneğin, , eşit veya eşit olmayan belirli bir değerle karşılaştırma geçerli değilse), IDE'den daha akıllı olmanız gerekir.

Sorulması gereken GERÇEK soru, <ve> ve <= ve> = 'nin niçin terimlerle eşzamanlı olarak uygulanması gereken karşılaştırmalı işleçler için çiftler olduğudur! (A <b) == a> = b ve! (A> b) == a <= b. Birini geçersiz kılarsanız dördünü de uygulamanız gerekir ve muhtemelen == (ve! =) De geçersiz kılmanız gerekir, çünkü a anlamsalsa (a <= b) == (a == b) b'ye eşittir.


14

Özel türünüz için == aşırı yüklüyorsanız ve! = Değilse, her şey nesneden türetildiğinden! = Nesne için! = Nesnesi tarafından işlenecektir ve bu, CustomType! = CustomType'tan çok farklı olacaktır.

Ayrıca dil yaratıcıları muhtemelen kodlayıcılar için en fazla esnekliğe izin vermek için bu şekilde istediler ve aynı zamanda ne yapmak istediğiniz hakkında varsayımlar yapmamalarını istediler.



2
Esneklik nedeni, dışarıda bırakmaya karar verdikleri birçok özelliğe de uygulanabilir, örneğin blogs.msdn.com/b/ericlippert/archive/2011/06/23/… . eşitlik operatörlerinin uygulanması.
Stefan Dragnev

Bu çok ilginç. Yararlı bir özellik gibi görünüyor. Bunu neden dışarıda bırakacakları hakkında hiçbir fikrim yok.
Chris Mullins

11

Aklıma ilk gelen şey:

  • Test eşitsizliği, eşitliği test etmekten çok daha hızlıysa ne olur ?
  • Ne bazı durumlarda ise İade etmek istediğiniz falseiçin hem ==ve!= (yani onlar nedense karşılaştırıldığında edilemezse)

5
İlk durumda, eşitsizlik testi açısından eşitlik testi uygulayabilirsiniz.
Stefan Dragnev

İkinci durum, özel türünüzü onlarla birlikte kullanırsanız Dictionaryve Listkullanırsanız yapıları kıracaktır.
Stefan Dragnev

2
@ Stefante: operatörleri Dictionarykullanır GetHashCodeve kullanır Equals. Listkullanır Equals.
Dan Abramov

6

Muhtemelen bu sadece bir tasarım seçimi, ama dediğin x!= ygibi, aynı olmak zorunda değil.!(x == y) . Varsayılan bir uygulama eklemezseniz, belirli bir uygulamayı uygulamayı unutamayacağınızdan eminsiniz. Ve eğer gerçekten söylediğiniz kadar önemsizse, birini diğerini kullanarak uygulayabilirsiniz. Bunun 'kötü uygulama' olduğunu anlamıyorum.

C # ve Lua arasında başka farklılıklar da olabilir ...


1
Birini diğeri açısından uygulamak mükemmel bir uygulamadır. Ben sadece başka türlü yapıldığını gördüm - bu hata eğilimli.
Stefan Dragnev

3
Bu programcının sorunu, C # 'ın sorunu değil. Bu hakkı yerine getirmeyen programcılar diğer alanlarda da başarısız olacaktır.
GolezTrol

@GolezTrol: Bu Lua referansını açıklayabilir misiniz? Lua'ya hiç aşina değilim, ama referans bir şeye işaret ediyor gibi görünüyor.
zw324

@Ziyao Wei: OP, Lua'nın bunu C # 'dan farklı bir şekilde yaptığını belirtiyor (Lua görünüşte belirtilen operatörler için varsayılan meslektaşları ekliyor). Sadece böyle bir karşılaştırmayı önemsizleştirmeye çalışıyorum. Hiç fark yoksa, en azından birinin var olma hakkı yoktur. Lua'yı da bilmediğimi söylemeliyim.
GolezTrol

6

Sorunuzdaki anahtar kelimeler " neden " ve " zorunlu " dur .

Sonuç olarak:

Bu şekilde cevap vermek, çünkü öyle olacak şekilde tasarladıkları doğrudur ... ama sorunuzun "neden" bölümünü cevaplamamak.

Bazen bunların her ikisini de bağımsız olarak geçersiz kılmanın faydalı olabileceğini yanıtlamak doğrudur ... ancak sorunuzun "zorunluluk" bölümünü yanıtlamamak.

Bence basit cevap, C # için neden inandırıcı bir neden olmadığıdır. ikisini de geçersiz kılmanızı .

Dil, yalnızca geçersiz kılmak için izin vermelidir ==ve size bir varsayılan uygulamayı sağlamak !=olduğunu !söyledi. Siz de geçersiz kılmak istiyorsanız !=, buna sahip olun.

Bu iyi bir karar değildi. İnsanlar dil tasarlıyor, insanlar mükemmel değil, C # mükemmel değil. Omuz silkme ve QED


5

Buradaki mükemmel cevaplara eklemek için:

Bir operatöre adım atmaya çalıştığınızda ve hata ayıklayıcıda ne olacağını düşünün.!=== bunun yerine operatöre geçmeye ! Kafa karıştırıcı hakkında konuşun!

CLR'nin, birçok dilde çalışması gerektiği için operatörlerden birini veya diğerlerini bırakma özgürlüğüne izin vermesi mantıklıdır. Ama C # (CLR özelliklerini açığa değil örnekleri bol ref(: örn CLR kendisinde değil özellikleri uygulamanın örneklerinin örneğin döner ve yerli) ve bol using, lock, foreach, vs).


3

Programlama dilleri, son derece karmaşık mantıksal ifadenin sözdizimsel yeniden düzenlemeleridir. Bunu akılda tutarak, bir eşitsizlik vakası tanımlamaksızın bir eşitlik vakası tanımlayabilir misiniz? Cevap hayır. A nesnesinin b nesnesine eşit olması için a nesnesinin b'ye eşit olmayan tersi de doğru olmalıdır. Bunu göstermenin başka bir yolu da

if a == b then !(a != b)

bu, dilin nesnelerin eşitliğini belirlemesi için kesin bir yetenek sağlar. Örneğin, NULL! = NULL karşılaştırması, eşitlik dışı bir deyim uygulamayan bir eşitlik sistemi tanımına bir anahtar atabilir.

Şimdi! = Fikri ile ilgili olarak, sadece

if !(a==b) then a!=b

Bununla tartışamam. Bununla birlikte, büyük olasılıkla C # dil belirtim grubu tarafından programcının bir nesnenin eşitliğini ve eşitliğini birlikte tanımlamak zorunda kaldığı bir karardı.


Nullsadece bir sorun olurdu null, çünkü geçerli ==olmamakla birlikte, açık olmamakla birlikte, büyük ölçüde uygun olmalıdır. Şahsen, sadece büyük miktarda belirsiz, özensiz programlamaya izin verdiğini düşünüyorum.
nicodemus13

2

Kısacası, zorlanmış tutarlılık.

'==' ve '! =', nasıl tanımlasanız da, her zaman "eşittir" ve "eşit değil" sözlü tanımlarıyla tanımlanan gerçek karşıtlardır. Bunlardan yalnızca birini tanımlayarak, kendinizi '==' ve '! =' İfadelerinin hem doğru hem de her ikisinin de verilen iki değer için yanlış olabileceği bir eşitlik operatörü tutarsızlığına açarsınız. Her ikisini de tanımlamanız gerekir, çünkü birini tanımlamayı seçtiğinizde, diğerini de uygun şekilde tanımlamanız gerekir, böylece "eşitlik" tanımınızın ne olduğu açık bir şekilde anlaşılır. Derleyicinin diğer çözümü, yalnızca '==' VEYA '! =' Değerini geçersiz kılmanıza ve diğerini doğası gereği diğerini olumsuz olarak bırakmanıza izin vermektir. Açıkçası, C # derleyicisi ile durum böyle değil ve eminim ki '

Sormanız gereken soru "operatörleri neden geçersiz kılmam gerekiyor?" Bu güçlü bir akıl yürütmeyi gerektiren güçlü bir karardır. Nesneler için '==' ve '! =' Referans ile karşılaştırın. Referans olarak karşılaştırmak DEĞİL olarak bunları geçersiz kılarsanız, bu kodu inceleyen diğer geliştiriciler tarafından görülmeyen genel bir operatör tutarsızlığı yaratırsınız. "Bu iki örneğin durumu mu?" Sorusunu sormaya çalışıyorsanız, IEquatible'ı uygulamalı, Equals () tanımlamalı ve bu yöntem çağrısını kullanmalısınız.

Son olarak, IEquatable () aynı nedenden dolayı NotEquals () 'i tanımlamaz: eşitlik operatörü tutarsızlıklarını açma potansiyeli. NotEquals () DAİMA geri dönmelidir! Eşittir (). NotEquals () tanımını Equals () uygulayan sınıfa açarak, eşitliği belirlemede tutarlılık konusunu bir kez daha zorlayacaksınız.

Edit: Bu sadece benim muhakeme olduğunu.


Bu mantıksız. Sebep tutarlılık olsaydı, tam tersi geçerli olurdu: sadece uygulayabilirdiniz operator ==ve derleyici çıkarımda bulunurdu operator !=. Sonuçta, operator +ve bunun için yaptığı budur operator +=.
Konrad Rudolph

1
foo + = bar; foo = foo + bar için kestirme bir bileşik ödevdir; Bir operatör değil.
196

Gerçekten onlar vardır 'her zaman doğru karşıtların', o zaman bir neden olacaktır için otomatik tanımlama a != bolarak !(a == b)(C # ne sattığını olan) ....
andrewf

-3

Muhtemelen düşünmedikleri bir şeyin yapacak zamanları yoktu.

Ben == aşırı yüklerken ben her zaman yönteminizi kullanın. Sonra sadece diğerinde kullanıyorum.

Haklısınız, az miktarda çalışma ile derleyici bunu bize ücretsiz olarak verebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.