Linq, VB - анонимный тип не может быть преобразован в анонимный тип - PullRequest
3 голосов
/ 09 июля 2009

Я новичок Линк, может быть, кто-то может указать мне в правильном направлении. Что здесь не так? Кажется, что эти анонимные типы имеют одинаковые подписи.

          '*** Get all of the new list items'
          Dim dsNewFiles = From l1 In list1 _
                           Where Not (From l2 In list2 _
                                      Select l2.id, l2.timestamp).Contains(New With {l1.id, l1.timestamp})

Хотелось бы, чтобы в вышеприведенном коде был какой-то способ выделения, но я получаю ошибку компиляции:

Value of type '<anonymous type> (line n)' cannot be converted to '<anonymous type> (line n)'.

в ".Contains ( Новое с {l1.id, l1.timestamp} )"

Я предполагаю, что анонимные типы в некотором роде различны, но столбцы id и timestamp одинаковы в обоих списках. Они также в том же порядке. Чем еще они могут отличаться?

[Редактировать 10.07.2009 16:28 EST]

Я попробовал предложенный код от пользователя Meta-Knight (New With {Key l1.id, l1.timestamp}), и он исправил ошибку компиляции. Однако, когда я запустил код со списками List1 и List2 следующим образом:

List1                         List2
id     timestamp              id     timestamp
--     ----------             --     ----------
01     2009-07-10 00:00:00    01     2009-07-10 00:00:00

Результат был:

dsNewFiles
id     timestamp
--     ----------
01     2009-07-10 00:00:00

Это должен был быть пустой список.

Ответы [ 2 ]

1 голос
/ 10 июля 2009

Просто измените последнюю часть вашего кода на:

New With {Key l1.id, Key l1.timestamp}

Я проверил код, и он работает.

Edit:

Я не знаю, почему это не работает для вас, я опубликую весь код, просто чтобы быть уверенным.

Dim dsNewFiles = From l1 In list1 _
                           Where Not (From l2 In list2 _
                                      Select l2.ID, l2.TimeStamp).Contains(New With {Key l1.ID, Key l1.TimeStamp})

Другой вариант - просто сделать следующее:

Dim dsNewFiles = list1.Except(list2)

Чтобы это работало, ваш класс должен переопределить Equals и GetHashCode и реализовать интерфейс IEquatable (Of T). Вот очень хороший пример на MSDN (внизу).

Если ID и Timespan не представляют равенства в вашем классе, вы можете использовать пользовательский IEqualityComparer (Of T) в качестве второго аргумента.

1 голос
/ 09 июля 2009

Когда вы генерируете анонимные типы, они будут генерироваться как отдельные типы, если они не задают свои свойства с тем же именем и в том же точном порядке. Итак, ваш пример такой же, как если бы я сделал это:

Class A 
BeginClass 
    Begin ID as Int Begin ... End 
    Stuff as String Begin ... End 
EndClass

Class B 
BeginClass 
    Begin Stuff as String Begin ... End 
    ID as Int Begin ... End 
EndClass

From a In someListofAs
Where Not (From b In someListofBs Select b).Contains(a)

Это полный воздушный код, кстати.

Кроме того, в вашем примере одна часть LINQ является анонимным, а другая - нет. Это может быть вашей проблемой.

Попробуйте это:

From l1 In list1 _
Where Not (From l2 In list2 _
    Select New With { ID = l2.id, Timestamp = l2.timestamp}).Contains(
        New With { ID = l1.id, Timestamp = l1.timestamp})
...