class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>
{
new Book
{
Name="C# in Depth",
Authors = new List<Author>
{
new Author
{
FirstName = "Jon", LastName="Skeet"
},
new Author
{
FirstName = "Jon", LastName="Skeet"
},
}
},
new Book
{
Name="LINQ in Action",
Authors = new List<Author>
{
new Author
{
FirstName = "Fabrice", LastName="Marguerie"
},
new Author
{
FirstName = "Steve", LastName="Eichert"
},
new Author
{
FirstName = "Jim", LastName="Wooley"
},
}
},
};
var temp = books.SelectMany(book => book.Authors).Distinct();
foreach (var author in temp)
{
Console.WriteLine(author.FirstName + " " + author.LastName);
}
Console.Read();
}
}
public class Book
{
public string Name { get; set; }
public List<Author> Authors { get; set; }
}
public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override bool Equals(object obj)
{
return true;
//if (obj.GetType() != typeof(Author)) return false;
//else return ((Author)obj).FirstName == this.FirstName && ((Author)obj).FirstName == this.LastName;
}
}
Ini didasarkan pada contoh dalam "LINQ in Action". Daftar 4.16.
Ini mencetak Jon Skeet dua kali. Mengapa? Saya bahkan telah mencoba mengesampingkan metode Setara di kelas Penulis. Still Distinct sepertinya tidak berhasil. Apa yang saya lewatkan?
Sunting: Saya telah menambahkan == dan! = Kelebihan operator juga. Masih tidak ada bantuan.
public static bool operator ==(Author a, Author b)
{
return true;
}
public static bool operator !=(Author a, Author b)
{
return false;
}
sumber
IEquatable
(dan menimpaEquals
/GetHashCode
) tetapi tidak ada titik putus saya yang aktif dalam metode ini di LinqDistinct
?GetHashCode
danEquals
, mereka terkena selama loop foreach. Ini karenavar temp = books.SelectMany(book => book.Authors).Distinct();
return anIEnumerable
, artinya request tidak langsung dieksekusi, hanya dieksekusi saat data digunakan. Jika Anda ingin contoh penembakan ini segera, tambahkan.ToList()
setelah.Distinct()
dan Anda akan melihat breakpoints diEquals
danGetHashCode
sebelum foreach.The
Distinct()
kesetaraan referensi Metode pemeriksaan untuk jenis referensi. Ini berarti secara harfiah mencari objek yang sama digandakan, bukan objek berbeda yang berisi nilai yang sama.Ada kelebihan beban yang membutuhkan IEqualityComparer , sehingga Anda dapat menentukan logika yang berbeda untuk menentukan apakah suatu objek sama dengan yang lain.
Jika Anda ingin Penulis berperilaku seperti objek normal (yaitu hanya persamaan referensi), tetapi untuk tujuan persamaan periksa Distinct berdasarkan nilai nama, gunakan IEqualityComparer . Jika Anda selalu ingin objek Author dibandingkan berdasarkan nilai nama, maka timpa GetHashCode dan Equals , atau terapkan IEquatable .
Dua anggota pada
IEqualityComparer
antarmuka adalahEquals
danGetHashCode
. Logika Anda untuk menentukan apakah duaAuthor
objek sama tampaknya jika string nama Depan dan Belakang sama.sumber
Solusi lain tanpa implementasi
IEquatable
,Equals
danGetHashCode
adalah dengan menggunakanGroupBy
metode LINQs dan untuk memilih item pertama dari IGrouping.sumber
.GroupBy(y => new { y.FirstName, y.LastName })
Ada satu cara lagi untuk mendapatkan nilai yang berbeda dari daftar tipe data yang ditentukan pengguna:
Tentunya akan memberikan kumpulan data yang berbeda
sumber
Distinct()
melakukan perbandingan kesetaraan default pada objek di enumerable. Jika Anda belum digantiEquals()
danGetHashCode()
, kemudian menggunakan implementasi default padaobject
, yang membandingkan referensi.Solusi sederhana adalah menambahkan implementasi yang benar dari
Equals()
danGetHashCode()
ke semua kelas yang berpartisipasi dalam grafik objek yang Anda bandingkan (yaitu Buku dan Penulis).The
IEqualityComparer
antarmuka adalah kenyamanan yang memungkinkan Anda untuk menerapkanEquals()
danGetHashCode()
di kelas terpisah ketika Anda tidak memiliki akses ke internal kelas Anda perlu membandingkan, atau jika Anda menggunakan metode yang berbeda dari perbandingan.sumber
Anda telah mengganti Equals (), tetapi pastikan Anda juga mengganti GetHashCode ()
sumber
<custom>^base.GetHashCode()
Jawaban di atas salah !!! Berbeda seperti yang dinyatakan di MSDN mengembalikan Equator default yang dinyatakan Properti Default memeriksa apakah tipe T mengimplementasikan antarmuka System.IEquatable dan, jika demikian, mengembalikan EqualityComparer yang menggunakan implementasi itu. Jika tidak, ia mengembalikan EqualityComparer yang menggunakan penggantian Object.Equals dan Object.GetHashCode yang disediakan oleh T
Yang berarti selama Anda melebihi sama Anda baik-baik saja.
Alasan kode Anda tidak berfungsi adalah karena Anda memeriksa nama depan == nama belakang.
lihat https://msdn.microsoft.com/library/bb348436(v=vs.100).aspx dan https://msdn.microsoft.com/en-us/library/ms224763(v=vs.100).aspx
sumber
Anda dapat menggunakan metode ekstensi pada daftar yang memeriksa keunikan berdasarkan Hash yang dihitung. Anda juga dapat mengubah metode ekstensi untuk mendukung IEnumerable.
Contoh:
Metode Ekstensi:
sumber
Anda dapat mencapai ini dengan dua cara:
1. Anda dapat mengimplementasikan antarmuka IEquatable seperti yang ditunjukkan Enumerable.Distinct Method atau Anda dapat melihat jawaban @ skalb di posting ini
2. Jika objek Anda tidak memiliki kunci unik, Anda dapat menggunakan metode GroupBy untuk mencapai daftar objek berbeda, bahwa Anda harus mengelompokkan semua properti objek dan setelah memilih objek pertama.
Misalnya seperti di bawah ini dan bekerja untuk saya:
Kelas MyObject seperti di bawah ini:
3. Jika objek Anda memiliki kunci unik, Anda hanya dapat menggunakannya dalam kelompok dengan.
Misalnya kunci unik objek saya adalah Id.
sumber