1

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?

5
  • Are you using powergui by any chance? See this comment. Commented Nov 3, 2021 at 2:15
  • hmm no using vscode Commented Nov 3, 2021 at 2:19
  • 2
    It might be helpful to see your script code, or at least a minimal reproducible example. 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. Commented Nov 3, 2021 at 2:20
  • 1
    An individual DictionaryEntry has Key and Value properties. A Hashtable, by way of implementing IDictionary interface, has Keys and Values properties 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. Commented Nov 3, 2021 at 2:26
  • 2
    Though 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. Commented Nov 3, 2021 at 7:50

1 Answer 1

7

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.
  • 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).
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.