嵌套的多行lambda函数作为LINQ Select的参数导致错误

时间:2010-06-29 16:00:09

标签: .net vb.net linq lambda

我正在尝试在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中折叠到一行来修复其他行。但是,在这种情况下,我无法做到这一点。

2 个答案:

答案 0 :(得分:1)

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

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

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

这样可以避免潜在的副作用,因为你可以在方法中构造一个新类型的实例,并简化代码(包括使代码更容易测试,通过将逻辑重构为一个单独的方法来处理单个“实例”)。

答案 1 :(得分:0)

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