mcl*_*ton 10 syntax powershell pscustomobject psobject
我已经使用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])
Run Code Online (Sandbox Code Playgroud)
输出:
System.Collections.Hashtable
System.Collections.Hashtable
True
True
True
False
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
干杯,
中号
mkl*_*nt0 14
return和[pscustomobject]红鲱鱼在这里,在一个方式.
它归结为:
隐式/表达式输出与cmdlet生成的输出; 使用return落入前一类,使用Write-Output后者.
仅在cmdlet输出中包含大多数不可见[psobject]实例的对象.
# implicit / expression output: NO [psobject] wrapper:
@{ "aaa" = "bbb" } -is [psobject] # -> $False
# Cmdlet-produced output: [psobject]-wrapped
(Write-Output @{ "aaa" = "bbb" }) -is [psobject] # -> $True
Run Code Online (Sandbox Code Playgroud)
请注意 - 令人惊讶的[pscustomobject]是- [psobject]它们都是相同的:它们都引用了type [System.Management.Automation.PSObject],这是PowerShell在幕后使用的通常不可见的帮助器类型.
(为了增加混乱,存在是一个独立[System.Management.Automation.PSCustomObject]类型).
在大多数情况下,这个额外的[psobject]包装器是良性的 - 它主要表现为包装对象直接 - 但有些情况会导致微妙的不同行为(见下文).
有没有一种通用的方法我可以确定与代码的区别,除了显然检查我在变量中的每个哈希表是否也是一个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]!
Run Code Online (Sandbox Code Playgroud)
请注意,-as从Windows PowerShell v5.1/PowerShell Core v6.1.0开始,使用具有真实PS自定义对象的相关运算符将被破坏 - 请参阅下文.
作为额外[psobject]包装器是良性的情况的示例,您仍然可以直接测试其类型的包装对象:
(Write-Output @{ "aaa" = "bbb" }) -is [hashtable] # $True
Run Code Online (Sandbox Code Playgroud)
也就是说,尽管包装器-is仍然可以识别包装类型.因此,有些矛盾,既 -is [psobject]与-is [hashtable]返回$True在这种情况下,即使这些类型是不相关的.
这些差异并没有充分的理由,它们会让我感到漏洞抽象(实施):内部构造意外地从幕后偷看.
以下GitHub问题讨论了这些行为: