应该使用什么运算符来检测空的 psobject?

Jar*_*red 7 powershell

使用以下示例:

$test = '{ }' | ConvertFrom-Json
Run Code Online (Sandbox Code Playgroud)

如何检测 $test 为空?

不起作用:

$test -eq $null
-not $test
Run Code Online (Sandbox Code Playgroud)

这确实有效,但感觉不对:

$test.ToString() -eq ''
Run Code Online (Sandbox Code Playgroud)

这是一个简化的示例,但我的用例是我使用 invoke-restmethod 从 REST api 获得的响应,某些属性作为空 psobjects 返回。

mkl*_*nt0 10

[pscustomobject]通过字符串表示测试空(无属性)自定义对象 ( )的最简单解决方案,但您需要使用可扩展字符串(字符串插值,"..."而不是.ToString()获取它:

# Returns $True, if custom object $test is empty, i.e. has no properties
-not "$test"
Run Code Online (Sandbox Code Playgroud)

注意:-not $test.ToString() 应该是等价的,但目前(从 PowerShell Core 6.1 开始)不是,由于bug。存在错误时,任何 [pscustomobject]实例都会从返回空字符串.ToString()
另一种解决方法是使用.psobject.ToString().

只有空的(无属性的)自定义对象会字符串化为可扩展字符串内的空字符串,并在 PowerShell 中将空字符串强制转换为布尔值$False,而任何非空字符串都会产生$True

另一种方法是将一个空字符串作为 LHS进行比较,这隐式强制[pscustomobject]RHS 上的 被字符串化:

# NOTE: Works ONLY with '' on the LHS.
'' -eq $test
Run Code Online (Sandbox Code Playgroud)

一个概念上更清晰的方法,虽然它依赖于.psobjectPowerShell 添加到所有对象的隐藏属性,包含反射信息:

0 -eq @($test.psobject.Properties).Count
Run Code Online (Sandbox Code Playgroud)

请注意需要使用@(...)强制枚举属性,以便可以对它们进行计数 - 请参阅下一节。

上述方法很方便,但如果$test是一个具有许多属性的大对象,它可能会很昂贵——尽管从绝对意义上讲,这在实践中可能很少有影响。


一个更便宜但更模糊的解决方案是访问.psobject.Properties集合而不枚举其所有成员:

# Returns $true, if $test has no properties
-not $test.psobject.Properties.GetEnumerator().MoveNext()
Run Code Online (Sandbox Code Playgroud)

.psobject.Properties集合显然是懒惰的枚举,因此没有.Count属性;.GetEnumerator().MoveNext()因此using是一种将枚举限制为第一个属性(如果有)的方法。


至于你尝试什么

$test -eq $null
Run Code Online (Sandbox Code Playgroud)

$test仍然是一个对象,即使它碰巧没有属性,并且一个对象根据定义是 never $null

-not $test
Run Code Online (Sandbox Code Playgroud)

PowerShell 的隐式到布尔转换将任何 [pscustomobject]实例视为$True,无论它是否具有属性;例如,[bool] ([pscustomobject] @{})产量$True

要了解如何将其他数据类型强制转换为布尔值,请参阅此答案