Daniel
Daniel

Reputation: 11054

Linq, VB - Anonymous type cannot be converted to anonymous type

I'm a Linq noobie, maybe someone can point me in the right direction. What's wrong here? These anonymous types seem to have the same signatures.

          '*** 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})

I wish there were some way to highlight in the above code, but I get the compile error:

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

on the ".Contains(New With{l1.id, l1.timestamp})"

I assume it thinks the anonymous types are different in some way, but the id and timestamp columns are the same in either list. They are also in the same order. What else can be different between the two?

[Edit 7/10/2009 16:28 EST]

I tried the suggested code from user Meta-Knight (New With {Key l1.id, l1.timestamp}) and it fixed the compile error. However, when I ran the code with List1 and List2 as follows:

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

The result was:

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

It should have been an empty list.

Upvotes: 3

Views: 4400

Answers (2)

Meta-Knight
Meta-Knight

Reputation: 17845

Just change the last part of your code to:

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

I tested the code and it works.

Edit:

I don't know why this doesn't work for you, I'll post the whole code just to be sure.

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})

Another option is to simply do the following:

Dim dsNewFiles = list1.Except(list2)

For this to work, your class must override Equals and GetHashCode, and implement the IEquatable(Of T) interface. There's a very good example on MSDN (at the bottom).

If ID and Timespan don't represent equality in your class, you can use a custom IEqualityComparer(Of T) as a second argument.

Upvotes: 1

Joseph
Joseph

Reputation: 25513

When you generate anonymous types, they will be generated as separate types if they don't specify their properties with the same name and in the same exact order. So your example is the same as if I did this:

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)

That's complete air code, btw.

Also, in your example one part of your LINQ is an anonymous type and the other isn't. That might be your problem.

Try this:

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})

Upvotes: 1

Related Questions