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?
1 Answer
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
.Valuecan not be used to return the individual entries'.Valueproperty values.- Instead, use the type-native
.Valuesproperty, as shown above (or.Keys, to get the collection of keys).
- Instead, use the type-native
[hashtable]and when you have one, you are for some reason returning aDictionaryEntry.DictionaryEntryhasKeyandValueproperties. AHashtable, by way of implementingIDictionaryinterface, hasKeysandValuesproperties that return all keys and all values, respectively. It sounds like how properties are handled for collections is what you're seeing, though it seems like when you access the single entry it must not be through a collection.