powershell,[object[]]::new(10) 和 new-object object[] 10 之间的区别

Pey*_*yre 4 powershell

我有一种我不明白的奇怪行为。创建的所有数组不都是相等的吗?

\n
$a1=[object[]]::new(15)\n$a1.gettype()\n\nIsPublic IsSerial Name                                     BaseType\n-------- -------- ----                                     --------\nTrue     True     Object[]                                 System.Array\n\n$a1.length\n15\n\n0..14|%{$a1[$_]=$_}\n
Run Code Online (Sandbox Code Playgroud)\n

第 10 个元素的字符串格式按预期工作。

\n
'{10}' -f $a1\n10\n
Run Code Online (Sandbox Code Playgroud)\n

但...

\n
$a2=new-object object[] 15\n$a2.gettype()\n\nIsPublic IsSerial Name                                     BaseType\n-------- -------- ----                                     --------\nTrue     True     Object[]                                 System.Array\n\n\n$a2.length\n15\n\n0..14|%{$a2[$_]=$_}\n
Run Code Online (Sandbox Code Playgroud)\n

完全相同的字符串格式化请求会引发错误,就好像$a2数组太小一样

\n
'{10}' -f $a2\nErreur lors de la mise en forme d\xe2\x80\x99une cha\xc3\xaene : L'index (de base z\xc3\xa9ro) doit \xc3\xaatre sup\xc3\xa9rieur ou \xc3\xa9gal \xc3\xa0 z\xc3\xa9ro et inf\xc3\xa9rieur \xc3\xa0 la taille de la liste des arguments..\nAu caract\xc3\xa8re Ligne:1 : 1\n+ '{10}' -f $a2\n+ ~~~~~~~~~~~~~\n    + CategoryInfo          : InvalidOperation : ({10}:String) [], RuntimeException\n    + FullyQualifiedErrorId : FormatError\n
Run Code Online (Sandbox Code Playgroud)\n

我错过了什么吗?我哪里错了?

\n

mkl*_*nt0 5

该行为是一个已知的错误

由于New-Objectcmdlet(命令)而不是表达式(例如[object[]]::new(15)),因此其输出对象包装在[psobject]实例中。

通常,这些不可见的[psobject]包装器是良性的,并且包装器呈现得好像它是被包装的对象本身。

但是,在某些情况下,此类包装器的存在会干扰功能,例如您的情况:

-f运算符无法识别[psobject]这样的 -wrapped 数组,这会导致您看到的问题:

用人工包裹的数组来模拟问题[psobject]

# !! Error:
#  "Index (zero based) must be greater than or equal to zero and 
#   less than the size of the argument list."
# The [psobject]-wrapped array is treated as a *single* object so -f
# sees no *2nd* value ({1})
# Omitting the [psobject] cast works as expected.
'{1}' -f [psobject] ('a', 'b')

# Ditto, with New-Object, 
# which *invariably and implicitly* returns the array in a [psobject] wrapper.
'{1}' -f (New-Object string[] 2)
Run Code Online (Sandbox Code Playgroud)

相关 GitHub 问题:


解决方法:

  • 正如您所注意到的,通过PowerShell在所有 .NET 类型(需要 v5+ 的 PowerShell)上公开的内在静态方法(例如)使用构造函数表达式,不会出现问题,因为此时不涉及不可见的包装器。::new()[object[]]::new(15)[psobject]

    • 鉴于此方法更有效,并且使用构造函数调用中使用的熟悉的方法语法,因此值得优先选择它New-Object
  • 在 PowerShell v4- 中,使用通过内部属性.psobject.BaseObject来解决该问题,该属性返回包装的数组:psobject

    $a2 = (New-Object object[] 15).psobject.BaseObject
    '{10}' -f $a2  # OK
    
    Run Code Online (Sandbox Code Playgroud)