【问题标题】:Linq, VB - Anonymous type cannot be converted to anonymous typeLinq,VB - 匿名类型无法转换为匿名类型
【发布时间】:2009-07-09 16:37:06
【问题描述】:

我是 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)'.

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

我假设它认为匿名类型在某些方面有所不同,但两个列表中的 id 和 timestamp 列是相同的。它们的顺序也相同。两者之间还有什么不同?

[编辑 2009 年 7 月 10 日 16:28 EST]

我尝试了用户 Meta-Knight 的建议代码(带有 {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

它应该是一个空列表。

【问题讨论】:

    标签: vb.net linq anonymous-types


    【解决方案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) 作为第二个参数。

    【讨论】:

    • @Meta-Knight:感谢您的洞察力。编译错误消失了。但是,代码仍然不能像预期的那样工作。请参阅上面的编辑。
    【解决方案2】:

    当您生成匿名类型时,如果它们没有以相同的名称和相同的确切顺序指定它们的属性,它们将被生成为单独的类型。所以你的例子和我这样做是一样的:

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

    【讨论】:

    • 啊。我知道了。知道如何做我想做的事情吗?
    • 我在那里看到了您的编辑...我认为这行不通,至少看起来不行。不是和上面一样吗?两个新的“Withs”都会创建不同签名的对象?
    • @hypoxide 没有两个签名在我看来是一样的。除非我打错了我没有看到的东西。试试看你会得到什么,我面前没有VS,否则我会尝试。
    • @Joseph:是的,但是从我如何理解您对上述示例中为什么我无法比较生成的匿名类型的解释来看,在我看来这同样适用于这些类型。尽管它们的签名看起来相同,但它们的某些东西本质上是不同的,以至于它们不能像它们是同一类型一样进行比较?也许我需要在这里使用 lambda 函数作为比较方法?为了记录,我确实尝试过。虽然它运行正常,但它不起作用。 List1 和 List2 包含相同的集合,但上述操作的结果产生了所有 List1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    相关资源
    最近更新 更多