【问题标题】:Is it possible to create a non-modifiable hashtable in PowerShell?是否可以在 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'
            }

或者替代ReadOnlyConstant 用于不可删除的变量。

我假设使用ReadOnly 选项我将无法修改集合,但事实并非如此。例如,$STANDARD_TOKEN_PARAMS.someNewEntry = 'newEntry' 有效并相应地修改集合。

是否有类似的命令可用于在 PowerShell 中创建真正的“只读”集合?

【问题讨论】:

    标签: powershell readonly-collection


    【解决方案1】:

    选项ReadOnlyConstant变量(数据持有者)概念:它们只防止为变量分配新值,它们不会防止修改只读/常量变量不可变存储的

    为了防止修改值(对象)本身,你必须另外使用只读的数据类型[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.ReadOnlyDictionary2[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

    【讨论】:

      猜你喜欢
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      • 2014-09-30
      • 2022-07-06
      • 1970-01-01
      相关资源
      最近更新 更多