有人可以解释哈希表的 Add_member 和 $hashTable.Something 之间的区别吗?
Can someone explain the difference between Add_member and $hashTable.Something for a 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?怎么会这样?
@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
这里已经有很好的信息,但让我从概念上分解一下:
hashtable(键值对)的 条目 与其 .NET 类型的 成员(属性、方法、事件).
哈希表条目是 数据,可通过 System.Collections.Hashtable
类型的 成员 访问,特别是 .Keys
和 .Values
属性和 parameterized .Item
属性,PowerShell(如 C#)通过 index 语法在语法上显示:
- 也就是说,您可以通过在
[...]
中使用其键来获取条目的值,作为 .Item(...)
的语法糖;例如,
@{ foo = 42 }['foo']
是 @{ foo = 42 }.Item('foo')
的快捷方式
此外,PowerShell 允许您使用点符号访问条目值,使用.
,member-access operator - 即使您访问的不是 成员 ,而是哈希表条目;例如
@{ foo = 42 }.foo
等同于 @{ foo = 42 }['foo']
.
换句话说:
PowerShell 的 .
(点符号)可以访问 两者:
- 键入 成员 按名称
- entry values by key,对于哈希表和
[ordered]
哈希表 - 更一般地说,实现 System.Collections.IDictionary
interface or its generic counterpart, System.Collections.Generic.IDictionary<TKey, TValue>
.[1] 的类型
如果存在 名称冲突,条目 访问优先 - 例如,@{ Count = 42 }.Count
returns 42
而不是反映条目数的 type-native Count
属性 的值;要访问后者,请在 属性 名称前加上 get_
并将其作为 方法 调用:@{ Count = 42 }.get_Count()
returns 1
, 条目数。
注意:Add-Member
adds to an object aren't technically .NET type members (type-native properties and methods), but in PowerShell they act as such. (Such members, which are a feature of PowerShell's ETS (Extended Type System) 的成员仅由 PowerShell 知道,并且必须与它们关联的对象分开维护。)
换句话说:您的 Add-Member
调用添加了一个新的 属性 (NoteProperty
) 而不是 entry 到哈希表实例,以及实例的类型原生属性,例如 .Count
、.Keys
和 .Values
.
关于 表面处理 条目与成员:
由于哈希表的默认输出格式仅显示其 条目,因此您添加的任何 (ETS) 成员不会在输出中显示 - 您必须显式访问 .SomethingAddMember
属性;你也可以通过反射,使用Get-Member
($Hashtable | Get-Member SomethingAddMember
)
看到它
虽然 ETS 属性通常很少出现,但它们在 序列化上下文中出现 ,例如使用 ConvertTo-Json
,并且 在哈希表(字典)的情况下,您会得到 ETS 属性的 mix 和 entries,也就是你看到的:
在许多情况下,PowerShell 将哈希表(字典)视为常规对象,其中哈希表的 条目 - 而不是哈希表对象的真实类型原生属性 - 使用 代替属性 .
但是,ETS属性仍然包含在内,[2]导致上述混合。
[1] 奇怪的是,如果 key 类型恰好是 [object]
,虽然这不是典型的,因为 generic type/interface 的重点是使用 specific 类型 - 请参阅GitHub issue #15997.
[2] 从 PowerShell 7.2 开始,ConvertTo-Json
不再为 [datetime]
和 [string]
实例序列化 ETS 属性(参见 GitHub PR #15665), but other serialization cmdlets such as ConvertTo-Csv
仍然如此。
在相关说明中,从 PowerShell 7.2 开始,当 ConvertTo-Json
确实包含 ETS 属性时,如果 ETS 属性 恰好 override 原生类型 - 见 GitHub issue #13998.
假设我有一个哈希表:
$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?怎么会这样?
@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
这里已经有很好的信息,但让我从概念上分解一下:
hashtable(键值对)的 条目 与其 .NET 类型的 成员(属性、方法、事件).
哈希表条目是 数据,可通过 System.Collections.Hashtable
类型的 成员 访问,特别是 .Keys
和 .Values
属性和 parameterized .Item
属性,PowerShell(如 C#)通过 index 语法在语法上显示:
- 也就是说,您可以通过在
[...]
中使用其键来获取条目的值,作为.Item(...)
的语法糖;例如,
@{ foo = 42 }['foo']
是@{ foo = 42 }.Item('foo')
的快捷方式
此外,PowerShell 允许您使用点符号访问条目值,使用.
,member-access operator - 即使您访问的不是 成员 ,而是哈希表条目;例如
@{ foo = 42 }.foo
等同于 @{ foo = 42 }['foo']
.
换句话说:
PowerShell 的
.
(点符号)可以访问 两者:- 键入 成员 按名称
- entry values by key,对于哈希表和
[ordered]
哈希表 - 更一般地说,实现System.Collections.IDictionary
interface or its generic counterpart,System.Collections.Generic.IDictionary<TKey, TValue>
.[1] 的类型
如果存在 名称冲突,条目 访问优先 - 例如,
@{ Count = 42 }.Count
returns42
而不是反映条目数的 type-nativeCount
属性 的值;要访问后者,请在 属性 名称前加上get_
并将其作为 方法 调用:@{ Count = 42 }.get_Count()
returns1
, 条目数。
注意:Add-Member
adds to an object aren't technically .NET type members (type-native properties and methods), but in PowerShell they act as such. (Such members, which are a feature of PowerShell's ETS (Extended Type System) 的成员仅由 PowerShell 知道,并且必须与它们关联的对象分开维护。)
换句话说:您的 Add-Member
调用添加了一个新的 属性 (NoteProperty
) 而不是 entry 到哈希表实例,以及实例的类型原生属性,例如 .Count
、.Keys
和 .Values
.
关于 表面处理 条目与成员:
由于哈希表的默认输出格式仅显示其 条目,因此您添加的任何 (ETS) 成员不会在输出中显示 - 您必须显式访问
看到它.SomethingAddMember
属性;你也可以通过反射,使用Get-Member
($Hashtable | Get-Member SomethingAddMember
)虽然 ETS 属性通常很少出现,但它们在 序列化上下文中出现 ,例如使用
ConvertTo-Json
,并且 在哈希表(字典)的情况下,您会得到 ETS 属性的 mix 和 entries,也就是你看到的:在许多情况下,PowerShell 将哈希表(字典)视为常规对象,其中哈希表的 条目 - 而不是哈希表对象的真实类型原生属性 - 使用 代替属性 .
但是,ETS属性仍然包含在内,[2]导致上述混合。
[1] 奇怪的是,如果 key 类型恰好是 [object]
,虽然这不是典型的,因为 generic type/interface 的重点是使用 specific 类型 - 请参阅GitHub issue #15997.
[2] 从 PowerShell 7.2 开始,ConvertTo-Json
不再为 [datetime]
和 [string]
实例序列化 ETS 属性(参见 GitHub PR #15665), but other serialization cmdlets such as ConvertTo-Csv
仍然如此。
在相关说明中,从 PowerShell 7.2 开始,当 ConvertTo-Json
确实包含 ETS 属性时,如果 ETS 属性 恰好 override 原生类型 - 见 GitHub issue #13998.