是否可以在 PowerShell 中创建不可修改的哈希表?
Posted
技术标签:
【中文标题】是否可以在 PowerShell 中创建不可修改的哈希表?【英文标题】:Is it possible to create a non-modifiable hashtable in PowerShell? 【发布时间】:2021-06-25 16:32:50 【问题描述】:我熟悉使用 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 中创建真正的“只读”集合?
【问题讨论】:
【参考方案1】:选项ReadOnly
和Constant
是变量(数据持有者)概念:它们只防止为变量分配新值,它们不会防止修改只读/常量变量不可变存储的值。
为了防止修改值(对象)本身,你必须另外使用只读的数据类型[1]来存储在只读/常数变量。要获取只读哈希表(字典),请使用通用 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]
实例,因为需要 通用 IDictionary
-实现具有匹配类型的实例;因此,使用了一个辅助的System.Collections.Generic.Dictionar[TKey, TValue]
实例。
注意 [System.StringComparer]::OrdinalIgnoreCase
参数传递给辅助。字典,确保键查找不区分大小写,它们在 PowerShell [hashtables]
中的默认方式。[2]
虽然生成的 $STANDARD_TOKEN_PARAMS
只读变量的 值 实际上也是只读的,但意外尝试修改只读字典会导致不明显的错误消息,截至PowerShell 核心 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".
仅使用 点表示法 会提供有用的错误消息:$STANDARD_TOKEN_PARAMS.Username = 'foo'
报告 Collection is read-only.
GitHub issue #15118 建议改进这些错误消息。
[1] 这不是总是必要的,也就是说,如果值是定义 不可变 .NET 原始类型(属性-less 类型,例如 [int]
) 或 [string]
。
[2] 请注意,Windows PowerShell 和(过时的)PowerShell Core 6.1 及更低版本中的[hashtable]
使用[System.StringComparer]::CurrentCultureIgnoreCase
,即文化敏感 改为查找 - 有关背景信息,请参阅 this GitHub issue。
【讨论】:
以上是关于是否可以在 PowerShell 中创建不可修改的哈希表?的主要内容,如果未能解决你的问题,请参考以下文章
我在 ActiveDirectory 中创建了一个新的自定义属性。如何在 PowerShell 中修改它?
我在哪里可以找到可以在 Powershell 中创建的所有 COM 对象?
在 Powershell 中创建 PerformanceCounterCategory