2012-11-11 15 views
11

Tôi đã đọc một cuốn sách về Linq, và thấy rằng phương pháp Distinct có một quá tải mà phải mất một so sánh. Đây sẽ là một giải pháp tốt cho một vấn đề tôi có nơi tôi muốn có được các thực thể riêng biệt từ một bộ sưu tập, nhưng muốn so sánh được trên ID thực thể, ngay cả khi các thuộc tính khác là khác nhau.Làm cách nào để sử dụng trình so sánh tùy chỉnh với phương pháp Linq Distinct?

Theo cuốn sách, nếu tôi có một thực thể Gribulator, tôi sẽ có thể tạo ra một Comparer như thế này ...

private class GribulatorComparer : IComparer<Gribulator> { 
    public int Compare(Gribulator g1, Gribulator g2) { 
    return g1.ID.CompareTo(g2.ID); 
    } 
} 

... và sau đó sử dụng nó như thế này ...

List<Gribulator> distinctGribulators 
    = myGribulators.Distinct(new GribulatorComparer()).ToList(); 

Tuy nhiên, điều này mang đến cho các lỗi biên dịch sau đây ...

'System.Collections.Generic.List' không chứa một định nghĩa cho 'biệt' và phần mở rộng phương pháp quá tải tốt nhất 'System.Linq.Enumerable .Distinct (System.Collections.Generic.IEnumerable, System.Collections.Generic.IEqualityComparer) 'có một số đối số không hợp lệ

Đối số 2: không thể chuyển đổi từ' LinqPlayground.Program.GribulatorComparer 'thành' System.Collections.Generic.IEqualityComparer '

Tôi đã tìm kiếm xung quanh một chút và đã thấy nhiều ví dụ sử dụng mã như thế này, nhưng không có khiếu nại về lỗi trình biên dịch.

Tôi đang làm gì sai? Ngoài ra, đây có phải là cách tốt nhất để làm điều này? Tôi muốn một giải pháp một lần ở đây, vì vậy không muốn bắt đầu thay đổi mã cho chính thực thể đó. Tôi muốn thực thể vẫn giữ nguyên như bình thường, nhưng chỉ ở một nơi này, so sánh chỉ với ID.

Cảm ơn bạn đã được trợ giúp.

+0

Quên thêm, tôi đang sử dụng VS2012, và .NET 4.0 trong C# –

Trả lời

13

Bạn đang thực hiện Comparer bạn như là một IComparer<T>, phương pháp quá tải LINQ đòi hỏi một thực hiện IEqualityComparer:

private class GribulatorComparer : IEqualityComparer<Gribulator> { 
    public bool Equals(Gribulator g1, Gribulator g2) { 
    return g1.ID == g2.ID; 
    } 
} 

chỉnh sửa:

Để làm rõ, giao diện IComparer thể được sử dụng để phân loại, như đó là cơ bản những gì phương pháp Compare().

Như thế này:

items.OrderBy(x => new ItemComparer()); 

private class ItemComparer : IComparer<Item> 
{ 
    public int Compare(Item x, Item y) 
    { 
     return x.Id.CompareTo(y.Id) 
    } 
} 

Mà sẽ sắp xếp bộ sưu tập của bạn sử dụng comparer đó, tuy nhiên LINQ cung cấp một cách để làm điều đó cho các lĩnh vực đơn giản (như một int Id).

items.OrderBy(x => x.Id); 
+0

Cảm ơn Peter, điều đó giải thích! Ví dụ tôi đang sử dụng trong cuốn sách là dành cho OrderBy, nhưng anh ta đã nhắc đến nó từ nơi anh ta thảo luận về Distinct, và tôi đã không chọn một thực tế là tôi cần một giao diện khác. Không phải là rất rõ ràng trong cuốn sách thực sự: ( –

+0

Nhân tiện, bạn có biết nếu có một cách để làm điều này với một chức năng nặc danh, thay vì phải tạo ra một lớp riêng biệt cho các so sánh? Có vẻ như overkill –

+0

Cho đến nay Tôi đã thực sự nghĩ về việc quá tải các toán tử LINQ với những thứ như thế –