Distinct in LINQ with anonymous types (in VB.NET)

后端 未结 5 1438
醉梦人生
醉梦人生 2020-12-16 20:29

Supposing the referenced List below contains 2 elements:

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


        
相关标签:
5条回答
  • 2020-12-16 21:02

    Distinct must know somehow which objects are the same. You select anonymus objects here, it doesn't know which are equal. I never wrote a single line of VB.Net, but I tried something, and it works:

    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
    

    In your case:

    Dim Countries = From c In List 
                    Select c.Country, c.CountryID Distinct
    
    0 讨论(0)
  • 2020-12-16 21:05

    There is the LINQ operator named Distinct(), which you can call like so:

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

    More information on Distinct here

    0 讨论(0)
  • 2020-12-16 21:06
    Dim distinctCountries = Countries.Distinct()
    

    This works for me when I stop on the last line in the debugger:

    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 讨论(0)
  • 2020-12-16 21:08
    Dim Countries = From c In List _
                     Select New With {.Country = c.Country, .CountryID = c.CountryID }.Distinct() 
    
    0 讨论(0)
  • 2020-12-16 21:10

    I can only assume you're dead set on the use of anonymous type as the answer given by Alex Peck is correct. (and I've upvoted it).

    However, this boils down to a VB.NET vs C# compiler discussion.

    In VB.NET, when an anonymous type is encountered only those properties declared as key properties can be used for comparison purposes. So in VB.NET without key, when you're attempting to do a distinct comparison, nothing will occur.

    Read all about it here.

    So first, to answer your question, this works with anonymous types:

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

    enter image description here

    This is why freedompeace's answer doesn't quite work.

    C# however the compiler is a little different.

    When an anonymous type is encountered and a comparison operation is needed the c# compiler overrides Equals and GetHashCode. It will iterate over all of the public properties of the anonymous type to compute the object's hash code to test for equality.

    And you can read more about that here.

    Hope this answers your question.

    0 讨论(0)
提交回复
热议问题