Inilah yang saya temukan sebagai metode pada kelas yang diwarisi oleh banyak kelas saya yang lain. Idenya adalah memungkinkan perbandingan sederhana antara properti Objek dari Jenis yang sama.
Sekarang, ini berhasil - tetapi untuk meningkatkan kualitas kode saya, saya pikir saya akan membuangnya untuk diperiksa. Bagaimana bisa lebih baik / lebih efisien / dll.?
/// <summary>
/// Compare property values (as strings)
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool PropertiesEqual(object comparisonObject)
{
Type sourceType = this.GetType();
Type destinationType = comparisonObject.GetType();
if (sourceType == destinationType)
{
PropertyInfo[] sourceProperties = sourceType.GetProperties();
foreach (PropertyInfo pi in sourceProperties)
{
if ((sourceType.GetProperty(pi.Name).GetValue(this, null) == null && destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null) == null))
{
// if both are null, don't try to compare (throws exception)
}
else if (!(sourceType.GetProperty(pi.Name).GetValue(this, null).ToString() == destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null).ToString()))
{
// only need one property to be different to fail Equals.
return false;
}
}
}
else
{
throw new ArgumentException("Comparison object must be of the same type.","comparisonObject");
}
return true;
}
c#
object
properties
comparison
nailitdown
sumber
sumber
Jawaban:
Saya sedang mencari potongan kode yang akan melakukan sesuatu yang mirip untuk membantu menulis uji unit. Inilah yang akhirnya saya gunakan.
EDIT:
Kode yang sama seperti di atas tetapi menggunakan metode LINQ dan Ekstensi:
sumber
UPDATE: Versi terbaru Compare-Net-Objects terletak di GitHub , memiliki paket NuGet dan Tutorial . Bisa disebut suka
Atau jika Anda perlu mengubah beberapa konfigurasi, gunakan
Daftar lengkap parameter yang dapat dikonfigurasi ada di ComparisonConfig.cs
Jawaban asli:
Batasan yang saya lihat di kode Anda:
Yang terbesar adalah ia tidak melakukan perbandingan objek yang dalam.
Itu tidak melakukan perbandingan elemen dengan elemen dalam kasus properti adalah daftar atau berisi daftar sebagai elemen (ini bisa menjadi n-level).
Ini tidak memperhitungkan bahwa beberapa jenis properti tidak boleh dibandingkan (misalnya, properti Func yang digunakan untuk tujuan pemfilteran, seperti yang ada di kelas PagedCollectionView).
Itu tidak melacak properti apa yang sebenarnya berbeda (sehingga Anda dapat menampilkan dalam pernyataan Anda).
Hari ini saya mencari beberapa solusi untuk tujuan pengujian unit untuk melakukan perbandingan mendalam properti dengan properti dan saya akhirnya menggunakan: http://comparenetobjects.codeplex.com .
Ini adalah perpustakaan gratis dengan hanya satu kelas yang dapat Anda gunakan seperti ini:
Juga, dapat dengan mudah dikompilasi ulang untuk Silverlight. Cukup salin satu kelas ke dalam proyek Silverlight dan hapus satu atau dua baris kode untuk perbandingan yang tidak tersedia di Silverlight, seperti perbandingan anggota pribadi.
sumber
IgnoreObjectTypes
pengaturan mungkin berguna bila ada jenis yang berbeda.DifferencesString
telah dikoreksi di kelas CompareObjects. Tapi sekarang Anda bisa mendapatkannya dari ComparisonResult sebagai gantinya:var r = compareObjects.Compare(objectA, objectB); Assert.IsTrue(r.AreEqual, r.DifferencesString);
Saya pikir akan lebih baik untuk mengikuti pola untuk Override Object # Equals ()
Untuk penjelasan yang lebih baik: Baca C # Efektif Bill Wagner - Item 9 menurut saya
Pembaruan-Des 2011:
sumber
Jika kinerja tidak penting, Anda dapat membuat serial dan membandingkan hasilnya:
sumber
Saya pikir jawaban Big T cukup bagus tetapi perbandingan yang dalam tidak ada, jadi saya mengubahnya sedikit:
sumber
Saya akan menambahkan baris berikut ke metode PublicInstancePropertiesEqual untuk menghindari kesalahan salin & tempel:
sumber
Apakah Anda mengganti .ToString () pada semua objek Anda yang ada di properti? Jika tidak, perbandingan kedua itu bisa menghasilkan nol.
Juga, dalam perbandingan kedua itu, saya ragu tentang konstruksi! (A == B) dibandingkan dengan (A! = B), dalam hal keterbacaan enam bulan / dua tahun dari sekarang. Garisnya sendiri cukup lebar, yang tidak masalah jika Anda memiliki monitor yang lebar, tetapi mungkin tidak dapat mencetak dengan baik. (nitpick)
Apakah semua objek Anda selalu menggunakan properti sehingga kode ini akan berfungsi? Mungkinkah ada beberapa data internal non-properti yang dapat berbeda dari satu objek ke objek lainnya, tetapi semua data yang terekspos sama? Saya memikirkan beberapa data yang dapat berubah seiring waktu, seperti dua generator angka acak yang kebetulan mengenai nomor yang sama pada satu titik, tetapi akan menghasilkan dua urutan informasi yang berbeda, atau hanya data apa pun yang tidak terekspos. melalui antarmuka properti.
sumber
Jika Anda hanya membandingkan objek dengan tipe yang sama atau lebih jauh di rantai pewarisan, mengapa tidak menentukan parameter sebagai tipe dasar Anda, daripada objek?
Juga lakukan pemeriksaan nol pada parameter juga.
Selanjutnya saya akan menggunakan 'var' hanya untuk membuat kode lebih mudah dibaca (jika kode c # 3)
Selain itu, jika objek memiliki tipe referensi sebagai properti maka Anda hanya memanggil ToString () padanya yang tidak benar-benar membandingkan nilai. Jika ToString tidak diganti maka itu hanya akan mengembalikan nama tipe sebagai string yang dapat mengembalikan positif palsu.
sumber
Hal pertama yang saya sarankan adalah membagi perbandingan sebenarnya sehingga sedikit lebih mudah dibaca (saya juga telah mengeluarkan ToString () - apakah itu diperlukan?):
Saran selanjutnya adalah meminimalkan penggunaan refleksi sebanyak mungkin - ini sangat lambat. Maksudku, sangat lambat. Jika Anda akan melakukan ini, saya sarankan untuk menyimpan referensi properti ke cache. Saya tidak terlalu familiar dengan Reflection API, jadi jika ini sedikit salah, sesuaikan saja untuk membuatnya dikompilasi:
Namun, saya harus mengatakan bahwa saya setuju dengan poster lainnya. Ini berbau malas dan tidak efisien. Anda harus mengimplementasikan IComparable sebagai gantinya :-).
sumber
di sini direvisi satu untuk memperlakukan null = null sebagai sama
sumber
Saya akhirnya melakukan ini:
Pemakaian:
Memperbarui
Jika Anda ingin mengabaikan beberapa properti dengan nama:
Pemakaian:
sumber
Anda dapat mengoptimalkan kode Anda dengan memanggil GetProperties hanya sekali per jenis:
sumber
Untuk kelengkapan saya ingin menambahkan referensi ke http://www.cyotek.com/blog/comparing-the-properties-of-two-objects-via-reflection Ini memiliki logika yang lebih lengkap daripada kebanyakan jawaban lain di halaman ini.
Namun saya lebih suka Bandingkan-Net-Objects perpustakaan https://github.com/GregFinzer/Compare-Net-Objects (disebut oleh Liviu Trifoi 's jawaban )
Perpustakaan memiliki nuget paket http://www.nuget.org/packages/ BandingkanNETObjects dan beberapa opsi untuk dikonfigurasi.
sumber
Pastikan objek tidak
null
.Memiliki
obj1
danobj2
:sumber
Ini berfungsi bahkan jika objeknya berbeda. Anda dapat menyesuaikan metode di kelas utilitas mungkin Anda ingin membandingkan properti pribadi juga ...
sumber
Pembaruan atas jawaban Liviu di atas - CompareObjects.DifferencesString sudah tidak digunakan lagi.
Ini bekerja dengan baik dalam pengujian unit:
sumber
Assert.IsTrue(result.AreEqual, result.DifferencesString);
Metode ini akan mendapatkan
properties
kelas dan membandingkan nilai untuk masing-masingproperty
. Jika salah satu nilainya berbeda, itu akan terjadireturn false
, jika tidak maka akan berbedareturn true
.Pemakaian:
bool isEqual = Compare<Employee>(Object1, Object2)
sumber
Untuk memperluas jawaban @nawfal: s, saya menggunakan ini untuk menguji objek dari berbagai jenis dalam pengujian unit saya untuk membandingkan nama properti yang sama. Dalam kasus saya, entitas database dan DTO.
Digunakan seperti ini dalam pengujian saya;
sumber
terkadang Anda tidak ingin membandingkan semua properti publik dan hanya ingin membandingkan subsetnya saja, jadi dalam hal ini Anda cukup memindahkan logika untuk membandingkan daftar properti yang diinginkan ke kelas abstrak
dan gunakan kelas abstrak ini nanti untuk membandingkan objek
sumber
solusi saya terinspirasi dari jawaban Aras Alenin di atas dimana saya menambahkan satu tingkat perbandingan objek dan objek khusus untuk hasil perbandingan. Saya juga tertarik untuk mendapatkan nama properti dengan nama objek:
Menggunakan kelas berikut untuk menyimpan hasil perbandingan
Dan uji unit sampel:
sumber