I have a script that returns a DictionaryEntry collection, I've noticed if that dict happens to only have one K/V pair that I must specify var.value vs if it has multiple its var.values ! what gives? is there a common way to resolve this? in one command?
-
Are you using [tag:powergui] by any chance? [See this comment](https://stackoverflow.com/questions/36090764/powershell-hash-table-storing-values-of-system-collections-dictionaryentry#comment59826420_36090764). – briantist Nov 03 '21 at 02:15
-
hmm no using vscode – Tony Nov 03 '21 at 02:19
-
2It might be helpful to see your script code, or at least a [mcve]. It sounds to me like when you have multiple entries you're returning a real `[hashtable]` and when you have one, you are for some reason returning a `DictionaryEntry`. – briantist Nov 03 '21 at 02:20
-
1An individual `DictionaryEntry` has `Key` and `Value` properties. A `Hashtable`, by way of implementing [`IDictionary` interface](https://docs.microsoft.com/dotnet/api/system.collections.idictionary), has `Keys` and `Values` properties that return all keys and all values, respectively. It sounds like [how properties are handled for collections](https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_properties#properties-of-scalar-objects-and-collections) is what you're seeing, though it seems like when you access the single entry it must not be through a collection. – Lance U. Matthews Nov 03 '21 at 02:26
-
2Though it yielded a quality answer, this question leaves a lot to be desired. I'd recommend _showing_ rather than (barely) _describing_ the code as well as not relying on abbreviations. – Lance U. Matthews Nov 03 '21 at 07:50
1 Answers
if that dict happens to only have one K/V pair that I must specify var
.value
No: The implication is that you're dealing with an isolated key-value pair or a (non-dictionary) collection (array) of such pairs, such as [System.Collections.DictionaryEntry]
instances, that aren't part of a (single) dictionary (hashtable):
# Single key-value pair
$kvPair = [System.Collections.DictionaryEntry]::new('foo', 42)
$kvPair.Value # -> 42
# Array of key-value pairs
(
[System.Collections.DictionaryEntry]::new('foo', 42),
[System.Collections.DictionaryEntry]::new('bar', 43)
).Value # -> 42, 43
The fact that .Value
works even on an (array-like) collection of key-value pairs - even though .Value
is a property of that collection's individual elements - is owed to PowerShell's member-access enumeration feature.
By contrast, .Values
is a type-native property of a dictionary (hashtable) object. Such an object contains a (typically unordered) internal collection of key-value pairs with distinct keys, whose values the .Values
property returns as a collection; using a [hashtable]
literal as an example:
# Single-entry hashtable.
@{ foo = 42 }.Values # -> @(42) (single-element collection)
# Multi-entry hashtable.
@{ foo = 42; bar = 43 }.Values # -> 42, 43
Note, however, that - unlike with member-access enumeration - the .Values
property always returns a collection, even if that collection happens to contain just one element.
PowerShell considers a dictionary / hashtable a single object, which has two implications:
It is sent as whole to the pipeline.
- To request sending its entries (key-value pairs), one by one, instead, you must call
.GetEnumerator()
explicitly.
- To request sending its entries (key-value pairs), one by one, instead, you must call
Member-access enumeration is not applied, so that
.Value
can not be used to return the individual entries'.Value
property values.- Instead, use the type-native
.Values
property, as shown above (or.Keys
, to get the collection of keys).
- Instead, use the type-native

- 382,024
- 64
- 607
- 775