Saya sedang menulis pembungkus untuk elemen XML yang memungkinkan pengembang untuk dengan mudah mengurai atribut dari XML. Pembungkus tidak memiliki status selain objek yang dibungkus.
Saya sedang mempertimbangkan implementasi berikut (disederhanakan untuk contoh ini) yang mencakup kelebihan bagi ==
operator.
class XmlWrapper
{
protected readonly XElement _element;
public XmlWrapper(XElement element)
{
_element = element;
}
public string NameAttribute
{
get
{
//Get the value of the name attribute
}
set
{
//Set the value of the name attribute
}
}
public override bool Equals(object other)
{
var o = other as XmlWrapper;
if (o == null) return false;
return _element.Equals(o._element);
}
public override int GetHashCode()
{
return _element.GetHashCode();
}
static public bool operator == (XmlWrapper lhs, XmlWrapper rhs)
{
if (ReferenceEquals(lhs, null) && ReferenceEquals(rhs, null)) return true;
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null)) return false;
return lhs._element == rhs._element;
}
static public bool operator != (XmlWrapper lhs, XmlWrapper rhs)
{
return !(lhs == rhs);
}
}
Seperti yang saya mengerti c # idiomatik, ==
operator adalah untuk referensi kesetaraan sedangkan Equals()
metode untuk kesetaraan nilai. Tetapi dalam kasus ini, "nilai" hanyalah referensi ke objek yang dibungkus. Jadi saya tidak jelas apa yang konvensional atau idiomatik untuk c #.
Misalnya, dalam kode ini ...
var underlyingElement = new XElement("Foo");
var a = new XmlWrapper(underlyingElement);
var b = new XmlWrapper(underlyingElement);
a.NameAttribute = "Hello";
b.NameAttribute = "World";
if (a == b)
{
Console.WriteLine("The wrappers a and b are the same.");
}
.... haruskah keluaran program "Pembungkus a dan b sama"? Atau apakah itu aneh, yaitu melanggar prinsip paling tidak heran ?
Equals
saya tidak pernah mengalahkan==
(tapi tidak pernah sebaliknya). Apakah malas idiomatis? Jika saya mendapatkan perilaku yang berbeda tanpa pemeran eksplisit yang melanggar paling tidak heran.Jawaban:
Karena referensi ke bungkus
XElement
tidak dapat diubah, tidak ada perbedaan yang dapat diamati secara eksternal antara dua contohXmlWrapper
bungkus itu dengan elemen yang sama, jadi masuk akal untuk membebani==
untuk mencerminkan fakta ini.Kode klien hampir selalu peduli tentang kesetaraan logis (yang, secara default, diimplementasikan menggunakan persamaan referensi untuk jenis referensi). Fakta bahwa ada dua contoh pada heap adalah detail implementasi yang tidak perlu dipedulikan oleh klien (dan yang akan digunakan
Object.ReferenceEquals
secara langsung).sumber
Jika Anda pikir itu yang paling masuk akal
Pertanyaan dan jawaban adalah masalah harapan pengembang , ini bukan persyaratan teknis.
JIKA Anda menganggap pembungkus untuk tidak memiliki identitas dan membuatnya murni berdasarkan isinya, maka jawaban untuk pertanyaan Anda adalah ya.
Tapi ini masalah berulang. Haruskah dua pembungkus menunjukkan kesetaraan ketika mereka membungkus benda yang berbeda tetapi dengan kedua benda memiliki konten yang sama persis?
Jawabannya berulang. JIKA objek konten tidak memiliki identitas pribadi dan sebagai gantinya murni ditentukan oleh konten mereka, maka objek konten secara efektif adalah pembungkus yang akan menunjukkan kesetaraan. Jika Anda kemudian membungkus objek konten dalam pembungkus lain, pembungkus (tambahan) itu juga harus menunjukkan kesetaraan.
Ini kura - kura sepanjang jalan .
Tip umum
Setiap kali Anda menyimpang dari perilaku default, itu harus didokumentasikan secara eksplisit. Sebagai pengembang, saya berharap bahwa dua tipe referensi tidak akan menunjukkan kesetaraan bahkan jika isinya sama. Jika Anda mengubah perilaku itu, saya sarankan Anda mendokumentasikannya dengan jelas sehingga semua pengembang mengetahui perilaku tidak lazim ini.
Itu adalah perilaku default-nya, tetapi ini bukan aturan yang tidak bisa digerakkan. Ini masalah konvensi, tetapi konvensi dapat diubah jika dapat dibenarkan .
string
adalah contoh yang bagus di sini, seperti==
juga pemeriksaan kesetaraan nilai (bahkan ketika tidak ada string magang!). Mengapa? Sederhananya: karena memiliki string berperilaku seperti objek nilai terasa lebih intuitif untuk sebagian besar pengembang.Jika basis kode Anda (atau kehidupan pengembang Anda) dapat disederhanakan dengan meminta pembungkus Anda menunjukkan kesetaraan nilai di seluruh papan, lakukan (tapi dokumentasikan ).
Jika Anda tidak pernah memerlukan pemeriksaan kesetaraan referensi (atau mereka dianggap tidak berguna oleh domain bisnis Anda), maka tidak ada gunanya menyimpan pemeriksaan kesetaraan referensi di sekitar. Lebih baik menggantinya dengan pemeriksaan kesetaraan nilai untuk mencegah kesalahan pengembang .
Namun, sadarilah bahwa jika Anda memerlukan referensi pemeriksaan kesetaraan nanti di kemudian hari, mengimplementasikannya mungkin membutuhkan upaya yang penting.
sumber
==
memeriksa kesetaraan referensi karena ini adalah perilaku default. Namun, jika==
benar-benar memeriksa kesetaraan nilai, saya berharap (yaitu mengharuskan) bahwa ini didokumentasikan secara eksplisit.I'm curious why you expect that reference types won't define content equality.
Mereka tidak mendefinisikannya secara default , tetapi itu tidak berarti itu tidak dapat dilakukan. Saya tidak pernah mengatakan itu tidak dapat (atau tidak seharusnya) dilakukan, saya hanya tidak berharap (yaitu menganggap) secara default.Anda pada dasarnya membandingkan string jadi saya akan heran jika dua pembungkus yang berisi konten XML yang sama tidak akan dianggap sama, apakah itu diperiksa menggunakan Persamaan atau ==.
Aturan idiomatik mungkin masuk akal untuk objek jenis referensi secara umum tetapi string khusus dalam arti idiomatik, Anda seharusnya memperlakukan dan menganggapnya sebagai nilai meskipun secara teknis mereka adalah tipe referensi.
Postfix Wrapper Anda menambah kebingungan. Itu pada dasarnya mengatakan "bukan elemen XML". Jadi, haruskah saya memperlakukannya sebagai tipe referensi? Semantik ini tidak masuk akal. Saya akan kurang bingung jika kelas itu bernama XmlContent. Ini menandakan kami peduli dengan konten, bukan detail implementasi teknis.
sumber