将有序哈希表传递给函数

Passing an ordered hashtable to a function

如何将有序哈希表传递给函数?

以下会引发错误:

The ordered attribute can be specified only on a hash literal node.

function doStuff {
    Param (
        [ordered]$theOrderedHashtable
    )
    $theOrderedHashtable
}

$datFileWithMinSizes  = [ordered]@{"FileA.DAT" = "4"; "FileB.DAT" = "5"; "FileC.DAT" = "91" ; "FileD.DAT" = "847"  }

doStuff -theOrderedHashtable $datFileWithMinSizes

以下顺序不正确:

function doStuff {
    Param (
        [Hashtable]$theOrderedHashtable = [ordered]@{}
    )
    $theOrderedHashtable
}

$datFileWithMinSizes  = [ordered]@{"FileA.DAT" = "4"; "FileB.DAT" = "5"; "FileC.DAT" = "91" ; "FileD.DAT" = "847"  }

doStuff -theOrderedHashtable $datFileWithMinSizes

目前我唯一能让它工作的方法是不指定类型如下,但我想指定类型:

function doStuff {
    Param (
        $theOrderedHashtable
    )
    $theOrderedHashtable
}

$datFileWithMinSizes  = [ordered]@{"FileA.DAT" = "4"; "FileB.DAT" = "5"; "FileC.DAT" = "91" ; "FileD.DAT" = "847"  }

doStuff -theOrderedHashtable $datFileWithMinSizes

使用完整类型名称:

function Do-Stuff {
    param(
        [System.Collections.Specialized.OrderedDictionary]$OrderedHashtable
    )
    $OrderedHashtable
}

要同时支持常规哈希表和有序字典,您必须使用单独的参数集:使用 [System.Collections.IDictionary] 接口,因为

function Do-Stuff {
    [CmdletBinding(DefaultParameterSetName='Ordered')]
    param(
        [Parameter(Mandatory=$true,Position=0,ParameterSetName='Ordered')]
        [System.Collections.Specialized.OrderedDictionary]$OrderedHashtable,

        [Parameter(Mandatory=$true,Position=0,ParameterSetName='Hashtable')]
        [hashtable]$Hashtable
    )
    if($PSCmdlet.ParameterSetName -eq 'Hashtable'){
        $OrderedHashtable = $Hashtable
    }
    $OrderedHashtable
}

Mathias 是对的,但我想指出有一种方法可以在不使用参数集的情况下接受这两种类型。

这两种类型都实现了 IDictionary 接口,因此您可以使用接口强类型化您的参数,然后是实现了接口将被接受:

function Do-Stuff {
    [CmdletBinding(DefaultParameterSetName='Ordered')]
    param(
        [Parameter(Mandatory=$true,Position=0,ParameterSetName='Ordered')]
        [System.Collections.IDictionary]$Dictionary
    )
    $Dictionary.GetType().FullName
}

这将同时接受:

C:\WINDOWS\system32\WindowsPowerShell\v1.0> do-stuff @{}
System.Collections.Hashtable

C:\WINDOWS\system32\WindowsPowerShell\v1.0> do-stuff ([ordered]@{})
System.Collections.Specialized.OrderedDictionary

类似地,如果你想只接受一个有序的字典(而不是只是特定的OrderedDictionary类型),你可以使用 IOrderedDictionary 接口,它是由上述类型实现的,而不是 [hashtable]:

function Do-Stuff {
    [CmdletBinding(DefaultParameterSetName='Ordered')]
    param(
        [Parameter(Mandatory=$true,Position=0,ParameterSetName='Ordered')]
        [System.Collections.Specialized.IOrderedDictionary]$Dictionary

    )

    $Dictionary.GetType().FullName
}

然后:

C:\WINDOWS\system32\WindowsPowerShell\v1.0> do-stuff ([ordered]@{})
System.Collections.Specialized.OrderedDictionary

C:\WINDOWS\system32\WindowsPowerShell\v1.0> do-stuff @{}
Do-Stuff : Cannot process argument transformation on parameter 'Dictionary'. Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type 
"System.Collections.Specialized.IOrderedDictionary".
At line:1 char:10
+ do-stuff @{}
+          ~~~
    + CategoryInfo          : InvalidData: (:) [Do-Stuff], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Do-Stuff

只需补充现有的有用答案:

什么错误信息

The ordered attribute can be specified only on a hash literal node.

想告诉你:

[ordered]语法糖,而且只在hashtable literals(@{ ... }).

您可以按如下方式确定有序哈希表文字的实际类型:

PS> ([ordered] @{ foo = 1 }).GetType().FullName
System.Collections.Specialized.OrderedDictionary

也就是说,PowerShell 中的有序哈希表文字是 [System.Collections.Specialized.OrderedDictionary].

类型的一个实例