Home > front end >  Cannot find an overload for "ToLookup" and the argument count: "2" LINQ
Cannot find an overload for "ToLookup" and the argument count: "2" LINQ

Time:07-12

I have a PowerShell script that runs every hour, it essentially updates product info through a drip process. The script is failing in the dev environment, but continues to work in prod and qual. The failure point is at a line that uses LINQ. Here is the script:

$productInfos = [pscustomobject]@{
    product_name = 'Television'
    price = 1000
    product_id = 101
    } | ForEach-Object{$_}

$productIdDelegate = [Func[object,int]] {$args[0].product_id}
$productInfos = [Linq.Enumerable]::ToLookup($productInfos, $productIdDelegate)

Technically, it fails on the last line. but the second to last line is included because while researching this issue, I found a lot of other posts that pointed out if the two arguments in the ToLookup linq function are not of the same type, it can cause this issue. The second to last line was the "supposed" fix for many users, but sadly not myself. I still receive the

Cannot find an overload for "ToLookup" and the argument count: "2"

I checked any dependencies on all 3 environments, and everything is the same. And, the powershell versions are the same on all as well.

CodePudding user response:

Even though the error doesn't give much details, from your currently reproducible code we can tell that the issue is because $productInfos is a single object of the type PSObject and this class does not implement IEnumerable Interface:

$productInfos = [pscustomobject]@{
    product_name = 'Television'
    price = 1000
    product_id = 101
}

$productInfos -is [System.Collections.IEnumerable] # => False

To ensure $productInfos is always an enumberable you can use the Array subexpression operator @( ):

@($productInfos) -is [System.Collections.IEnumerable] # => True

Casting [object[]] or [array] should also be an option:

[object[]] $productInfos -is [System.Collections.IEnumerable] # => True
[array] $productInfos -is [System.Collections.IEnumerable]    # => True

However above methods only work as long as $productInfos has at least 1 element, as opposed to @(..) which will always ensure an array:

The result is always an array of 0 or more objects.

To summarize:

$productInfos = [Linq.Enumerable]::ToLookup([object[]] $productInfos, $productIdDelegate)
$productInfos = [Linq.Enumerable]::ToLookup(@($productInfos), $productIdDelegate)
$productInfos = [Linq.Enumerable]::ToLookup([array] $productInfos, $productIdDelegate)

Are all valid options having what's explained above in consideration, if we're not sure if the variable will always be populated, the safest alternative will always be @(...):

# Returns Null instead of an error:

[Linq.Enumerable]::ToLookup(@(), $productIdDelegate)
  • Related