2010-06-29 5 views
1

J'essaie d'utiliser un lambda multi-ligne imbriqué Function dans VB.NET et j'obtiens une erreur. Voici ce que mon code ressemble à:La fonction lambda multi-ligne imbriquée en tant que paramètre pour LINQ Select provoque une erreur

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) 

Et voici le long message d'erreur:

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 

Il se sent comme je l'ai quelque chose de mal avec ma syntaxe parce que je l'ai fixé d'autres lignes par l'effondrement en ligne Functions sur une ligne lorsque cela est possible. Cependant, je ne peux pas faire ça dans ce cas.

+2

Pouvez-vous coller dans l'instruction ENTIER? L'erreur semble être causée par ce qui est "avant" le premier .Sélectionnez ... –

+0

Je ne pense pas que vous voulez vraiment Sélectionnez - ou plutôt ** que faites-vous avec des effets secondaires ?!?!? ** –

+0

@Reed J'ai collé dans la première ligne. La raison pour laquelle je l'avais laissée était parce que par lui-même, la première ligne ne jette pas une erreur. –

Répondre

1

Votre sélection est lancée car le compilateur ne peut pas déterminer le type approprié en raison de votre utilisation d'un type anonyme. Cela étant dit, c'est une mauvaise idée, en général, d'utiliser Select() pour exécuter du code qui provoque un effet secondaire, ce que vous faites dans ce cas.

Personnellement, j'abandonnerais cela dans une seule instruction LINQ, dans ce cas. Le LINQ est, à mon avis, en train de rendre cela plus complexe qu'il ne devrait l'être. Ma préférence, dans un cas comme celui-ci, serait de faire une seule fonction qui fait votre logique, et renvoie un type approprié, renseigné (non anonyme). Vous pourriez alors simplement refactoriser votre déclaration LINQ en un seul Select qui renvoie votre type connu. Cela éviterait les effets secondaires potentiels, puisque vous pourriez construire une nouvelle instance du type dans la méthode, et simplifier le code (y compris le rendre beaucoup plus facilement testable, en refactorisant la logique dans une méthode distincte qui a fonctionné sur une "instance" unique).

+0

Je pense que je comprends ce que vous dites. Si l'intention est de modifier les données, séparez cette étape de la requête LINQ. De cette façon, vous n'obtenez pas un effet secondaire du processus. –

+0

@Ben: Exactement. Cela signifie également que la méthode qui convertit les données peut fonctionner sur un seul élément et être ** testable **. Le mettre dans une déclaration LINQ embrouille le problème - puisque vous «interrogez» en modifiant. Cela peut fonctionner, mais il a la même odeur que d'essayer de modifier une collection en l'itérant sur une instruction foreach, etc ... –

0

Reactive Extension .NET La méthode d'extension Do() peut être un bon candidat si vous attendez seulement un effet secondaire. Après cela, vous pouvez utiliser la méthode de projection Select() comme d'habitude.

Questions connexes