我已经使用 PowerShell 多年了,我以为我已经掌握了它的一些更“古怪”的行为,但我遇到了一个我无法理解的问题.. .
我一直使用“return”从函数返回值,但最近我想我应该看看 Write-Output 作为替代方案。然而,PowerShell 就是 PowerShell,我发现了一些似乎没有意义的东西(至少对我来说):
function Invoke-X{ write-output @{ "aaa" = "bbb" } };
function Invoke-Y{ return @{ "aaa" = "bbb" } };
$x = Invoke-X;
$y = Invoke-Y;
write-host $x.GetType().FullName
write-host $y.GetType().FullName
write-host ($x -is [hashtable])
write-host ($y -is [hashtable])
write-host ($x -is [pscustomobject])
write-host ($y -is [pscustomobject])
输出:
System.Collections.Hashtable
System.Collections.Hashtable
True
True
True
False
$x 和 $y(或“write-output”和“return”)之间有什么区别,这意味着它们都是哈希表,但其中只有一个“-is”是 pscustomobject?除了明显检查变量中的每个哈希表是否也是 pscustomobject 之外,是否有一种通用方法可以确定与代码的差异?
我的 $PSVersionTable 看起来像这样,以防此行为特定于特定版本的 PowerShell:
Name Value
---- -----
PSVersion 5.1.16299.492
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.16299.492
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
干杯,
中号
最佳答案
return
和[pscustomobject]
在某种程度上,这是转移注意力的事情。
归根结底是:
隐式表达式输出与cmdlet生成的输出;使用
return
(没有 cmdlet 调用)属于前一类,使用Write-Output
进入后者。输出对象被包裹 - 大部分不可见 -
[psobject]
仅在cmdlet生成的输出中的实例。
# Expression output: NO [psobject] wrapper:
@{ "aaa" = "bbb" } -is [psobject] # -> $False
# Cmdlet-produced output: [psobject]-wrapped
(Write-Output @{ "aaa" = "bbb" }) -is [psobject] # -> $True
请注意 - 令人惊讶的是 - [pscustomobject]
与 [psobject]
相同:它们都引用类型 [System.Management.Automation.PSObject]
,这是 PowerShell 在幕后使用的通常不可见的帮助程序类型。
(更令人困惑的是,有一个单独的 [System.Management.Automation.PSCustomObject]
类型。)
在很大程度上,这个额外的[psobject]
包装器是良性的 - 它的行为大多与包装对象直接的行为相同 - 但在某些情况下它会导致细微不同的行为(见下文)。
And is there a generalised way I can determine the difference from code, other than obviously checking whether every hashtable I have in a variable is also a pscustomobject
请注意,哈希表不是 PS 自定义对象 - 它仅以这种方式出现 - 任何 - [psobject]
- 由于[pscustomobject]
而包裹的对象与 [psobject]
相同.
检测真正的 PS 自定义对象 - 使用 [pscustomobject] @{ ... }
创建或New-Object PSCustomObject
/New-Object PSObject
或由 cmdlet 生成,例如 Select-Object
和Import-Csv
- 使用:
$obj -is [System.Management.Automation.PSCustomObject] # NOT just [pscustomobject]!
请注意,使用相关的 -as
从 Windows PowerShell v5.1/PowerShell Core v6.1.0 开始,具有真正 PS 自定义对象的运算符已损坏 - 请参阅下文。
作为额外 [psobject]
的情况的示例包装器是良性的,您仍然可以直接测试包装对象的类型:
(Write-Output @{ "aaa" = "bbb" }) -is [hashtable] # $True
也就是说,尽管有包装器,-is
仍然可以识别包装类型。
因此,有点矛盾的是,两者 -is [psobject]
和-is [hashtable]
返回$True
在这种情况下,即使这些类型不相关。
这些差异没有充分的理由,而且它们给我的印象是有漏洞的抽象(实现):内部构造意外地从幕布后面窥视。
以下 GitHub 问题讨论这些行为:
关于PowerShell - 函数中的 "Write-Output"与 "return",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51177881/