是否可以在 PowerShell 中创建不可修改的哈希表?
Is it possible to create a non-modifiable hashtable in PowerShell?
我熟悉使用 Set-Variable
命令在 PowerShell 中创建只读变量和常量,如下所示:
Set-Variable -Option ReadOnly, AllScope -Name STANDARD_TOKEN_PARAMS -Force -Value @{
Username = 'username'
Password = 'password'
ClientId = 'clientID'
}
或者替代 ReadOnly
与 Constant
对于不可移动变量。
我假设使用 ReadOnly
选项我将无法修改集合,但事实并非如此。例如,$STANDARD_TOKEN_PARAMS.someNewEntry = 'newEntry'
有效并相应地修改集合。
是否有类似的命令可用于在 PowerShell 中创建真正的 'ReadOnly' 集合?
选项ReadOnly
和Constant
是变量(数据持有者)概念:它们只阻止分配新值 到变量,它们不会阻止修改 值 ,read-only/constant 变量不可变地存储。
为了同时防止修改值(对象)本身,您必须另外使用只读的数据类型[1]存储在 read-only/constant 变量中。要获得只读散列 table(字典),请使用通用 System.Collections.ObjectModel.ReadOnlyDictionary[TKey, TValue]
类型:
Set-Variable -Option ReadOnly, AllScope -Name STANDARD_TOKEN_PARAMS -Value $(
$dict = [System.Collections.Generic.Dictionary[string, string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$dict.Add('Username', 'username')
$dict.Add('Password', 'password')
$dict.Add('ClientId', 'clientID')
[System.Collections.ObjectModel.ReadOnlyDictionary[string, string]]::new($dict)
)
注:
不幸的是,您不能直接从 PowerShell [hashtable]
初始化 ReadOnlyDictionary[TKey, TValue]
实例,因为 generic IDictionary
- 需要 匹配类型 的实例;因此,使用辅助 System.Collections.Generic.Dictionar[TKey, TValue]
实例。
注意传递给辅助的 [System.StringComparer]::OrdinalIgnoreCase
参数。字典,它确保键查找不区分大小写,就像它们在 PowerShell [hashtables]
.[2][ 中的默认方式一样=37=]
虽然生成的 $STANDARD_TOKEN_PARAMS
只读变量的 value 实际上也是只读的,但意外尝试修改只读字典导致错误消息不明显,从 PowerShell Core 7.1 开始:
$STANDARD_TOKEN_PARAMS['Username'] = 'foo'
毫无帮助的报告:Unable to index into an object of type "System.Collections.ObjectModel.ReadOnlyDictionary
2[System.String,System.String]`
$STANDARD_TOKEN_PARAMS.Add('foo', 'bar')
毫无帮助的报告:Cannot find an overload for "Add" and the argument count: "2"
$STANDARD_TOKEN_PARAMS.Clear()
毫无帮助的报告:Cannot find an overload for "Clear" and the argument count: "0".
- Only using dot notation 提供有用的错误消息:
$STANDARD_TOKEN_PARAMS.Username = 'foo'
报告 Collection is read-only.
- GitHub issue #15118 建议改进这些错误消息。
[1] 这不是 always 必需的,也就是说,如果值是 a 根据定义的实例 immutable .NET 原始类型(属性-less 类型,例如 [int]
)或 [string]
.
[2] 请注意 [hashtable]
在 Windows PowerShell 和(过时的)PowerShell Core 版本 6.1 及以下使用 [System.StringComparer]::CurrentCultureIgnoreCase
,即 文化敏感 查找 - 请参阅 this GitHub issue 了解背景信息。
我熟悉使用 Set-Variable
命令在 PowerShell 中创建只读变量和常量,如下所示:
Set-Variable -Option ReadOnly, AllScope -Name STANDARD_TOKEN_PARAMS -Force -Value @{
Username = 'username'
Password = 'password'
ClientId = 'clientID'
}
或者替代 ReadOnly
与 Constant
对于不可移动变量。
我假设使用 ReadOnly
选项我将无法修改集合,但事实并非如此。例如,$STANDARD_TOKEN_PARAMS.someNewEntry = 'newEntry'
有效并相应地修改集合。
是否有类似的命令可用于在 PowerShell 中创建真正的 'ReadOnly' 集合?
选项ReadOnly
和Constant
是变量(数据持有者)概念:它们只阻止分配新值 到变量,它们不会阻止修改 值 ,read-only/constant 变量不可变地存储。
为了同时防止修改值(对象)本身,您必须另外使用只读的数据类型[1]存储在 read-only/constant 变量中。要获得只读散列 table(字典),请使用通用 System.Collections.ObjectModel.ReadOnlyDictionary[TKey, TValue]
类型:
Set-Variable -Option ReadOnly, AllScope -Name STANDARD_TOKEN_PARAMS -Value $(
$dict = [System.Collections.Generic.Dictionary[string, string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$dict.Add('Username', 'username')
$dict.Add('Password', 'password')
$dict.Add('ClientId', 'clientID')
[System.Collections.ObjectModel.ReadOnlyDictionary[string, string]]::new($dict)
)
注:
不幸的是,您不能直接从 PowerShell
[hashtable]
初始化ReadOnlyDictionary[TKey, TValue]
实例,因为 genericIDictionary
- 需要 匹配类型 的实例;因此,使用辅助System.Collections.Generic.Dictionar[TKey, TValue]
实例。注意传递给辅助的
[System.StringComparer]::OrdinalIgnoreCase
参数。字典,它确保键查找不区分大小写,就像它们在 PowerShell[hashtables]
.[2][ 中的默认方式一样=37=]虽然生成的
$STANDARD_TOKEN_PARAMS
只读变量的 value 实际上也是只读的,但意外尝试修改只读字典导致错误消息不明显,从 PowerShell Core 7.1 开始:$STANDARD_TOKEN_PARAMS['Username'] = 'foo'
毫无帮助的报告:Unable to index into an object of type "System.Collections.ObjectModel.ReadOnlyDictionary
2[System.String,System.String]`$STANDARD_TOKEN_PARAMS.Add('foo', 'bar')
毫无帮助的报告:Cannot find an overload for "Add" and the argument count: "2"
$STANDARD_TOKEN_PARAMS.Clear()
毫无帮助的报告:Cannot find an overload for "Clear" and the argument count: "0".
- Only using dot notation 提供有用的错误消息:
$STANDARD_TOKEN_PARAMS.Username = 'foo'
报告Collection is read-only.
- GitHub issue #15118 建议改进这些错误消息。
[1] 这不是 always 必需的,也就是说,如果值是 a 根据定义的实例 immutable .NET 原始类型(属性-less 类型,例如 [int]
)或 [string]
.
[2] 请注意 [hashtable]
在 Windows PowerShell 和(过时的)PowerShell Core 版本 6.1 及以下使用 [System.StringComparer]::CurrentCultureIgnoreCase
,即 文化敏感 查找 - 请参阅 this GitHub issue 了解背景信息。