我正在尝试在PowerShell中使用LINQ。看起来这应该是完全可能的,因为PowerShell是建立在.NET框架之上的,但我不能让它工作。例如,当我尝试以下(人为的)代码时:
$data = 0..10
[System.Linq.Enumerable]::Where($data, { param($x) $x -gt 5 })
我得到以下错误:
找不到“Where”和参数计数的重载:“2”。
不要介意这可以用Where-Object
来完成的事实。这个问题的重点不是要找到在PowerShell中执行此操作的惯用方法。如果我能使用LINQ,在PowerShell中完成一些任务会容易很多。
4条答案
按热度按时间bzzcjhmw1#
您的代码的问题是PowerShell无法决定
ScriptBlock
示例({ ... }
)应该转换为哪个特定的委托类型。所以它不能为Where
method的第二个泛型参数选择一个类型具体的委托示例化。而且它也没有语法来显式指定泛型参数。要解决此问题,您需要自己将ScriptBlock
示例强制转换为正确的委托类型:为什么
[Func[object, bool]]
可以工作,而[Func[int, bool]]
不能?因为您的
$data
是[object[]]
,而不是[int[]]
,因为PowerShell默认创建[object[]]
数组;但是,您可以显式构造[int[]]
示例:cx6n0qe32#
要补充PetSerAl's helpful answer,请使用更广泛的答案来匹配问题的通用标题:
注意:以下内容至少适用于PowerShell 7.3.x Direct 对LINQ的支持-语法与C#中的语法相当-正在讨论GitHub issue #2226中PowerShell Core 的 * 未来 * 版本。
在PowerShell中使用LINQ:
[System.Linq.Enumerable]
类型的 * 静态方法 * 调用,并将输入集合作为第一个参数传递给该类型。[Linq.Enumerable]::OrderBy([Linq.Enumerable]::Where($inputCollection, ...), ...)
,而不是$inputCollection.Where(...).OrderBy(...)
*辅助函数和类:
.Select()
,有接受泛型**Func<>
委托的参数(例如,Func<T,TResult>
可以使用PowerShell代码创建,通过应用于脚本块的转换**;例如:[Func[object, bool]] { $Args[0].ToString() -eq 'foo' }
Func<>
委托的第一个泛型类型参数必须与输入集合的元素类型匹配;请记住,PowerShell默认创建[object[]]
阵列。.Contains()
和.OrderBy
,有参数接受实现特定接口的对象,如IEqualityComparer<T>
和IComparer<T>
;此外,输入类型可能需要实现IEquatable<T>
,以便比较按预期工作,例如使用.Distinct()
;所有这些需要 * 编译类 ,通常用C#编写(尽管您可以通过将带有嵌入式C#代码的字符串传递给Add-Type
cmdlet,从PowerShell创建它们);但是,在PSv 5 +中,您也可以使用自定义PowerShell classes,但有一些 * 限制。*泛型方法:
*LINQ方法返回一个 lazy enumerable而不是一个实际的集合;也就是说,返回的不是实际的数据,而是在枚举时将产生数据的东西。
.Count
来获得结果计数,也不能 index 到迭代器中;但是,您可以使用member-access enumeration(提取正在枚举的对象的属性值)。[Linq.Enumerable]::ToArray(...)
**中。::ToList()
。有关所有LINQ方法的概述,包括示例,请参见this great article。
简而言之:从PowerShell使用LINQ很麻烦,只有在以下任何一种情况下才值得努力:
*性能至关重要-请参阅this article。
k5ifujac3#
如果你想实现类似LINQ的功能,那么PowerShell有一些cmdlet和函数,例如:
Select-Object
、Where-Object
、Sort-Object
、Group-Object
。它具有用于大多数LINQ功能的cmdlet,如投影,限制,排序,分组,分区等。请参阅Powershell One-Liners:集合和LINQ。
有关使用Linq以及如何使其更容易的更多细节,文章LINQ Through Powershell可能会有所帮助。
v440hwme4#
当我想在PowerShell中有一个稳定的排序时,我运行了LINQ(稳定:如果要排序的属性在两个(或更多)元素上具有相同的值:保持秩序)。Sort-Object有一个-Stable-Switch,但仅在PS 6.1+中。另外,.NET中泛型集合中的Sort()实现并不稳定,所以我遇到了LINQ,文档中说它是稳定的。
下面是我的(测试-)代码: