views:

922

answers:

2

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.

+1  A: 

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})
Joseph
Ah. I see. Any idea how to do what I'm trying to do there?
hypoxide
I see your edit there... I don't think that will work, at least it doesn't seem to be. Isn't it the same case as above? Both new "Withs" will create objects of differing signatures?
hypoxide
@hypoxide No both signatures look the same to me. Unless I mistyped something that I'm not seeing. Try it and see what you get, I don't have VS in front of me otherwise I'd try.
Joseph
@Joseph: Right, but from how I understood your explanation of why I can't compare generated anonymous types in the above example it seems to me that the same would apply to these types. Despite the fact that their signatures appear the same, something about them is inherently different such that they cannot be compared as if they were the same type? Perhaps I'd need to use a lambda function here as a method of comparison? For the record, I did try it. Though it runs properly, it doesn't work. List1 and List2 contain the same set, yet the result of the above operation yields all of List1.
hypoxide
+1  A: 

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.

Meta-Knight
@Meta-Knight: Thanks for the insight. The compile error went away. However, the code still doesn't work like expected. Please see the edit above.
hypoxide
I edited with more details and another alternative.
Meta-Knight