我已经使用PowerShell多年了,我以为我对它的一些``古怪''行为有所了解,但是我遇到了一个我不能做的事...
我一直使用“返回”从函数返回值,但是最近我想我可以看一下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”)之间有什么区别,这意味着它们都是哈希表,但只有一个“-是” 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]
在这里是红色鲱鱼。
归结为:
return
(无cmdlet调用)属于前一类,而使用Write-Output
属于后者。 [psobject]
实例。 # 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]
包装器是良性的-它的行为几乎直接像被包装的对象一样-但是在某些情况下,它会引起细微的不同行为(请参见下文)。请注意,哈希表不是PS自定义对象,因为
[psobject]
与[pscustomobject]
相同,所以它仅对-[psobject]
包裹的对象才显示。要检测由
[pscustomobject] @{ ... }
或New-Object PSCustomObject
/ New-Object PSObject
创建或由cmdlet(例如Select-Object
和Import-Csv
)生成的真实PS自定义对象,请使用:$obj -is [System.Management.Automation.PSCustomObject] # NOT just [pscustomobject]!
请注意,从Windows PowerShell v5.1 / PowerShell Core v6.1.0开始,将相关的
-as
运算符与真正的PS自定义对象一起使用已被破坏-参见下文。例如,多余的
[psobject]
包装器是良性的,您仍然可以直接测试包装对象的类型:(Write-Output @{ "aaa" = "bbb" }) -is [hashtable] # $True
也就是说,尽管有包装器,但
-is
仍然可以识别包装的类型。因此,有点矛盾的是,即使这些类型无关,在这种情况下,
-is [psobject]
和-is [hashtable]
都返回$True
。这些差异没有充分的理由,它们让我感到困惑的是抽象的(实现):内部结构意外地从幕后偷看。
以下GitHub问题讨论了这些行为:
[psobject]
-wrapped, sometimes causing unexpected behavior. [pscustomobject]
the same as [psobject]
, even though a distinct [System.Management.Automation.PSCustomObject]
type exists? [psobject]
cmdlet parameters be changed to [object]
? -as
operator does not recognize System.Management.Automation.PSCustomObject
instances as such。 关于powershell - PowerShell-函数中的 “Write-Output”与 “return”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51177881/