【问题标题】:Can someone explain the difference between Add_member and $hashTable.Something for a hashtable?有人可以解释一下 Add_member 和 $hashTable.Something 的哈希表的区别吗?
【发布时间】:2021-08-25 10:08:57
【问题描述】:

假设我有一个哈希表:

$HashTable = @{}

现在,当我想向 Hashtable 添加一些内容时,我通常会这样做:

$HashTable.Something = 'Something'

当我测试 $hashTable 时,它​​会显示这个输出:

$HashTable

Name                           Value                                                                                                                                     
----                           -----                                                                                                                                     
Something                      Something 

我的一位同事使用了 Add-Member:

$HashTable | Add-Member -NotePropertyName 'SomethingAddMember' -NotePropertyValue 'SomethingAddMember'

它可以工作,但是当你查看 $HashTable 时,它​​仍然只会显示:

$HashTable

Name                           Value                                                                                                                                     
----                           -----                                                                                                                                     
Something                      Something

当我运行这个 $HashTable.SomethingAddMember 时,它会出现:

$HashTable.SomethingAddMember

为什么它没有出现在 HashTable 本身中?当我将它转换为 Json 时,它又出现了!这有多令人困惑,还是我错过了什么?

$HashTable | ConvertTo-Json
{
    "Something":  "Something",
    "SomethingAddMember":  "SomethingAddMember"
}

是不是因为 Add-Member 向 HashTable 添加了一个新属性,而不是 Keys with Values?怎么会这样?

【问题讨论】:

  • “是不是因为 Add-Member 向 HashTable 添加了一个新属性,而不是 Keys with Values?” - 是的,这正是为什么:)

标签: powershell properties hashtable


【解决方案1】:

这里已经有很好的信息了,但让我从概念上分解一下:

hashtable(键值对)的条目不同于其 .NET 类型的成员(属性、方法、事件)强>。

哈希表条目是数据,可通过System.Collections.Hashtable 类型的成员 访问,特别是.Keys 和.Values 属性和参数化 .Item 属性,PowerShell(如 C#)通过 index 语法在语法上显示该属性:

  • 也就是说,您可以通过在[...] 中使用它的键来获取条目的值,作为.Item(...) 的语法糖;例如,
    @{ foo = 42 }['foo'] 是@{ foo = 42 }.Item('foo') 的快捷方式

另外,PowerShell 允许您使用.、member-access operator 访问条目值带有点表示法 - 即使您访问的不是一个成员,但是一个哈希表条目;例如
@{ foo = 42 }.foo 等价于@{ foo = 42 }['foo']。

换句话说:

  • PowerShell 的.(点表示法)可以访问两者:

  • 如果存在 名称冲突,则 entry 访问优先 - 例如,@{ Count = 42 }.Count 返回 42 而不是原生类型 @987654351 的值@属性反映条目的数量;要访问后者,请在属性名称前加上 get_ 并作为 方法 调用它:@{ Count = 42 }.get_Count() 返回 1,即条目计数。

注意:Add-Member 添加到对象的成员在技术上不是 .NET 类型 成员(类型原生属性和方法),但在 PowerShell 中它们是这样的 /em>。 (这些成员是 PowerShell's ETS (Extended Type System) 的一个功能,只有 PowerShell 知道,并且必须与它们关联的对象分开维护。)

换句话说:您的Add-Member 调用向哈希表实例添加了一个新的属性 (NoteProperty),而不是一个条目 ,以及实例的原生类型属性,例如 .Count、.Keys 和 .Values。

关于表面条目与成员:

  • 由于哈希表的默认输出格式仅显示其条目,因此您添加的任何 (ETS) 成员 都不会显示在输出中 - 您必须显式访问.SomethingAddMember 属性;你也可以通过 reflection 看到它,使用 Get-Member ($Hashtable | Get-Member SomethingAddMember)

  • 虽然 ETS 属性通常很少出现,但它们会在序列化上下文中出现,例如在使用 ConvertTo-Json 时和 在哈希表(字典)的情况下您将获得 ETS 属性和条目的混合,这就是您所看到的:

    • 在许多情况下,PowerShell 将哈希表(字典)视为常规对象,其中使用哈希表的 条目 - 而不是哈希表对象的真正类型原生属性 代替属性。

    • 但是,ETS 属性仍然包括在内,[2] 导致上述混合。


[1] 奇怪的是,如果 key 类型恰好是 [object],点符号 not 起作用,尽管这不是典型的,因为generic 类型/接口的关键在于使用 specific 类型 - 请参阅 GitHub issue #15997。

[2] 自 PowerShell 7.2 起,ConvertTo-Json 不再序列化 [datetime] 和 [string] 实例的 ETS 属性(请参阅 GitHub PR #15665),但其他序列化 cmdlet(例如 ConvertTo-Csv)仍然可以。 在相关说明中,从 PowerShell 7.2 开始,当 ConvertTo-Json 确实包含 ETS 属性时,如果 ETS 属性碰巧覆盖类型原生属性,它会意外使用类型原生属性的值 - 请参阅 @ 987654333@.

【讨论】:

    【解决方案2】:

    @mathiasrjessen 已经解释过了。以下是一些将显示它的命令。

    $Hash = @{'A' = 'now'; 'B' = 'then'}
    $Hash
    $Hash | Get-Member -MemberType Property,NoteProperty | Select-Object -Property Name,MemberType | Format-Table * -Force
    $Hash.Something = 'Something'
    $Hash
    $Hash | Get-Member -MemberType Property,NoteProperty | Select-Object -Property Name,MemberType | Format-Table * -Force
    $Hash | Add-Member -NotePropertyName 'SomethingAddMember' -NotePropertyValue 'SomethingAddMemberValue'
    $Hash
    $Hash.SomethingAddMember
    $Hash | Get-Member -MemberType Property,NoteProperty | Select-Object -Property Name,MemberType | Format-Table * -Force
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-04
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多