【问题标题】:Nested multi-line lambda Function as parameter for LINQ Select is causing an error嵌套的多行 lambda 函数作为 LINQ Select 的参数导致错误
【发布时间】:2010-06-29 16:00:08
【问题描述】:

我正在尝试在 VB.NET 中使用嵌套的多行 lambda Function 并遇到错误。这是我的代码的样子:

cartItems = cartItems.Select(Function(ci) New With {.CartItem = ci, .Discount = discountItems.FirstOrDefault(Function(di) di.SKU = ci.SKU)}) 
.Select(Function(k)
            If k.Discount Is Not Nothing Then
                k.CartItem.Discount = minNumberOfItemsDiscounted * k.Discount.DiscountAmount
            End If
            Return k.CartItem
        End Function)

这是很长的错误信息:

Error   1   Overload resolution failed because no accessible 'Select' can be called with these arguments:
    Extension method 'Public Function Select(Of TResult)(selector As System.Func(Of <anonymous type>, Integer, TResult)) As System.Collections.Generic.IEnumerable(Of TResult)' defined in 'System.Linq.Enumerable': Nested function does not have a signature that is compatible with delegate 'System.Func(Of <anonymous type>, Integer, TResult)'.
    Extension method 'Public Function Select(Of TResult)(selector As System.Func(Of <anonymous type>, Integer, TResult)) As System.Collections.Generic.IEnumerable(Of TResult)' defined in 'System.Linq.Enumerable': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    Extension method 'Public Function Select(Of TResult)(selector As System.Func(Of <anonymous type>, TResult)) As System.Collections.Generic.IEnumerable(Of TResult)' defined in 'System.Linq.Enumerable': 'Is' operator does not accept operands of type 'Integer'. Operands must be reference or nullable types.
    Extension method 'Public Function Select(Of TResult)(selector As System.Func(Of <anonymous type>, TResult)) As System.Collections.Generic.IEnumerable(Of TResult)' defined in 'System.Linq.Enumerable': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error. C:\_Dev Projects\CMS2000\Components\NET\HBCatalogPromo\CatalogPromotion\CatalogPromotion.ConsoleTest\Module1.vb 88  21  CatalogPromotion.ConsoleTest

感觉我的语法有问题,因为我已通过在可能的情况下将Functions 行折叠到一行来修复其他行。但是,在这种情况下我不能这样做。

【问题讨论】:

  • 你能粘贴整个声明吗?该错误似乎是由第一个“之前”的内容引起的 .Select...
  • 我不认为你真的想要 Select - 或者更确切地说 你在做什么用它的副作用?!?!?
  • @Reed 我粘贴在第一行。我将其省略的原因是因为第一行本身不会引发错误。
  • 请发布更多上下文。 cartItems 和 discountItems 列表中有哪些商品,它们有哪些字段?

标签: .net vb.net linq lambda


【解决方案1】:

由于您使用匿名类型,编译器无法确定适当的类型,因此您的选择正在抛出。

话虽如此,一般来说,使用 Select() 来运行会导致副作用的代码是个坏主意,在这种情况下您正在这样做。

在这种情况下,我个人会放弃在单个 LINQ 语句中执行此操作。在我看来,LINQ 导致这比它应该的更复杂。在这种情况下,我的偏好是创建一个执行您的逻辑的函数,并返回一个适当的、填充的(已知的、非匿名类型)。然后,您可以将您的 LINQ 语句重构为一个返回您已知类型的 Select。

这将避免潜在的副作用,因为您可以在方法中构造该类型的新实例,并简化代码(包括通过将逻辑重构为适用于单个“实例”)。

【讨论】:

  • 我想我明白你在说什么。如果目的是更改数据,请将该步骤与 LINQ 查询分开。这样您就不会从该过程中获得副作用。
  • @Ben:没错。这也意味着转换数据的方法可以在单个元素上工作,并且是可测试的。将其放入 LINQ 语句会混淆问题 - 因为您在修改时正在“查询”。它可以工作,但它与在 foreach 语句等中迭代集合时尝试修改集合具有相同的气味......
【解决方案2】:

Reactive Extension .NET 的 Do() 扩展方法可能是一个不错的选择,如果您只期望副作用。之后就可以正常使用 Select() 投影方法了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2018-08-29
    • 2011-09-07
    • 2019-08-23
    • 2016-07-23
    • 1970-01-01
    • 2017-12-20
    相关资源
    最近更新 更多