2011-07-02 24 views
7

Giả sử các tham chiếu List dưới đây chứa 2 yếu tố:biệt trong LINQ với các loại vô danh (trong VB.NET)

Dim Countries = From c In List _ 
       Select New With { .Country = c.Country, .CountryID = c.CountryID } 

mã trên trả về

.Country=Spain .CountryID = 1 
.Country=Spain .CountryID = 1 

Làm thế nào tôi có thể nhận được giá trị khác biệt? Truy vấn Countries nên chứa chỉ

.Country=Spain .CountryID = 1 
+0

này hóa ra lại là một câu hỏi thú vị Chocol8. – Khepri

Trả lời

32

Tôi chỉ có thể giả sử bạn đã chết khi sử dụng loại ẩn danh khi câu trả lời được đưa ra bởi Alex Peck là chính xác. (và tôi đã upvoted nó).

Tuy nhiên, điều này tóm tắt thành một cuộc thảo luận về trình biên dịch VB.NET và C#.

Trong VB.NET, khi một kiểu ẩn danh chỉ gặp phải những thuộc tính được khai báo là thuộc tính khóa có thể được sử dụng cho mục đích so sánh. Vì vậy, trong VB.NET mà không có chìa khóa, khi bạn đang cố gắng để làm một so sánh riêng biệt, không có gì sẽ xảy ra.

Read all about it here.

Vì vậy, đầu tiên, để trả lời câu hỏi của bạn, công trình này với loại vô danh:

Dim Countries = From c In List Select New With {Key c.CountryId, c.Country} Distinct.ToList 

enter image description here

Đây là lý do tại sao câu trả lời freedompeace của không khá làm việc.

C# tuy nhiên trình biên dịch hơi khác một chút.

Khi gặp phải loại ẩn danh và cần có thao tác so sánh, trình biên dịch C# sẽ ghi đè bằng và GetHashCode. Nó sẽ lặp qua tất cả các thuộc tính công khai của kiểu ẩn danh để tính toán mã băm của đối tượng để kiểm tra sự bình đẳng.

And you can read more about that here.

Hy vọng điều này sẽ trả lời câu hỏi của bạn.

+0

+1 thú vị, tôi giỏi hơn trong C# và không nhận thức được sự khác biệt ở đây. –

+0

@ Khepri Thật tuyệt vời! Cảm ơn! – OrElse

+0

Lưu ý quan trọng từ [bài viết MSDN] (http://msdn.microsoft.com/en-us/library/bb384767.aspx): > Thuộc tính trong loại ẩn danh được tạo bởi truy vấn luôn là thuộc tính quan trọng. Xem thêm [testcase] này (https://gist.github.com/janv8000/9407469). – janv8000

2

Có nhà điều hành LINQ tên biệt(), mà bạn có thể gọi như vậy:

Dim Countries = (From c In List _ 
      Select c.Country, c.CountryID).Distinct() 

Thông tin thêm về biệt here

+0

lonita: Điều này không hoạt động – OrElse

1
Dim Countries = From c In List _ 
       Select New With {.Country = c.Country, .CountryID = c.CountryID }.Distinct() 
+0

Điều này không hoạt động – OrElse

5
Dim distinctCountries = Countries.Distinct() 

Điều này phù hợp với tôi khi tôi dừng dòng cuối cùng trong trình gỡ lỗi:

Imports System.Text 

<TestClass()> 
Public Class UnitTest1 

    Class Test 
     Public Country As String 
     Public CountryID As Integer 
    End Class 

    <TestMethod()> 
    Public Sub TestMethod1() 

     Dim List(1) As Test 
     List(0) = New Test With {.Country = "Spain", .CountryID = 1} 
     List(1) = New Test With {.Country = "Spain", .CountryID = 1} 

     Dim Countries = From c In List Select c.Country, c.CountryID 

     Dim distinctCountries = Countries.Distinct() 
    End Sub 

End Class 
+0

Peck Điều này cũng không hoạt động. – OrElse

2

Sự khác biệt phải biết bằng cách nào đó đối tượng nào giống nhau. Bạn chọn các đối tượng ẩn danh ở đây, nó không biết bằng nhau. Tôi chưa từng viết một dòng VB nào.Net, nhưng tôi đã cố gắng một cái gì đó, và nó hoạt động:

Module Module1 

    Sub Main() 
     Dim countries As List(Of Country) = New List(Of Country) 
     Dim spain1 As Country = New Country() 
     Dim spain2 As Country = New Country() 
     Dim spain3 As Country = New Country() 
     Dim hungary As Country = New Country() 
     spain1.ID = 1 
     spain1.Name = "Spain" 
     spain2.ID = 1 
     spain2.Name = "Spain" 
     spain3.ID = 2 
     spain3.Name = "Spain" 
     hungary.ID = 3 
     hungary.Name = "Hungary" 
     countries.Add(spain1) 
     countries.Add(spain2) 
     countries.Add(spain3) 
     countries.Add(hungary) 

     Dim ctr = From c In countries Select c.Name, c.ID 
        Distinct 

     For Each c In ctr 
      Console.WriteLine(c) 
     Next 
    End Sub 

    Public Class Country 

     Protected _name As String 

     Protected _id As Long 

     Public Property Name() As String 
      Get 
       Return _name 
      End Get 
      Set(ByVal value As String) 
       _name = value 
      End Set 
     End Property 

     Public Property ID() As Long 
      Get 
       Return _id 
      End Get 
      Set(ByVal value As Long) 
       _id = value 
      End Set 
     End Property 

    End Class 
End Module 

Trong trường hợp của bạn:

Dim Countries = From c In List 
       Select c.Country, c.CountryID Distinct 
Các vấn đề liên quan