Различаются в LINQ с анонимными типами (в VB.NET) - PullRequest
8 голосов
/ 02 июля 2011

Предположим, что ссылка List ниже содержит 2 элемента:

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

код выше возвращает

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

Как я могу получить различные значения?Запрос Countries должен содержать только

.Country=Spain .CountryID = 1

Ответы [ 5 ]

35 голосов
/ 02 июля 2011

Я могу только предположить, что вы не можете использовать анонимный тип, поскольку ответ Алекса Пека верен. (и я проголосовал за это).

Однако это сводится к обсуждению компилятора VB.NET против C #.

В VB.NET, когда встречается анонимный тип, для сравнения можно использовать только те свойства, которые объявлены как ключевые свойства. Так что в VB.NET без ключа, когда вы пытаетесь провести четкое сравнение, ничего не произойдет.

Узнайте все об этом здесь.

Итак, сначала, чтобы ответить на ваш вопрос, это работает с анонимными типами:

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

enter image description here

Вот почему ответ Liberpeace не совсем работает.

C #, однако компилятор немного отличается.

Когда встречается анонимный тип и требуется операция сравнения, компилятор c # переопределяет Equals и GetHashCode. Он будет перебирать все открытые свойства анонимного типа, чтобы вычислить хеш-код объекта для проверки на равенство.

А об этом вы можете прочитать здесь.

Надеюсь, что это отвечает на ваш вопрос.

5 голосов
/ 02 июля 2011
Dim distinctCountries = Countries.Distinct()

Это работает для меня, когда я останавливаюсь на последней строке в отладчике:

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
2 голосов
/ 02 июля 2011

Различный должен как-то знать, какие объекты одинаковы.Вы выбираете анонимные объекты здесь, он не знает, какие равны.Я никогда не писал ни одной строки на VB.Net, но я что-то пробовал, и это работает:

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

В вашем случае:

Dim Countries = From c In List 
                Select c.Country, c.CountryID Distinct
2 голосов
/ 02 июля 2011

Существует оператор LINQ с именем Distinct (), который можно вызывать так:

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

Дополнительная информация о Distinct здесь

1 голос
/ 02 июля 2011
Dim Countries = From c In List _
                 Select New With {.Country = c.Country, .CountryID = c.CountryID }.Distinct() 
...