Linq,VB - 匿名类型无法转换为匿名类型

时间:2009-07-09 16:37:07

标签: vb.net linq anonymous-types

我是Linq noobie,也许有人可以指出我正确的方向。这有什么不对?这些匿名类型似乎具有相同的签名。

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

on“.Contains( New With {l1.id,l1.timestamp} )”

我认为它认为匿名类型在某种程度上是不同的,但id和timestamp列在任一列表中都是相同的。它们的顺序也是一样的。两者之间还有什么不同?

[编辑7/10/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 个答案:

答案 0 :(得分:1)

生成匿名类型时,如果它们未指定具有相同名称且具有相同顺序的属性,则它们将作为单独的类型生成。所以你的例子和我做的一样:

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

答案 1 :(得分:1)

只需将代码的最后一部分更改为:

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

我测试了代码并且它有效。

编辑:

我不知道为什么这对你不起作用,我会发布整个代码以确定。

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)接口。有一个很好的例子on MSDN(在底部)。

如果ID和Timespan在您的类中不表示相等,则可以使用自定义IEqualityComparer(Of T)作为第二个参数。