-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dot-Property Access for Hashtable/Dictionary keys HIDES property values #7758
Comments
Interestingly, the logic is reversed in the context of member enumeration (collection-level properties shadow element properties), which prompted #7445 (see #7445 (comment) in particular). To spell out the - obscure - workarounds: # Update: Via .psbase - as suggested by @SteveL-MSFT in #3176
# and as now also documented in about_hash-tables
PS> @{ Keys = "No keys for you!"; Foo = 'bar' }.psbase.Keys
Keys
Foo
# Also: .get_Keys()
PS> @{ Keys = "No keys for you!"; Foo = 'bar' }.get_Keys()
Keys
Foo
# Via .psobject.properties
PS> @{ Keys = "No keys for you!"; Foo = 'bar' }.psobject.properties['Keys'].Value
Keys
Foo |
The current behaviour is by design and has been this way since V1. And while the behaviour is problematic in some cases (e.g. accessing the
These are two entirely unrelated things. The hashtable behaviour predates member enumeration by about a decade. Historical note: this behaviour dates from the earliest iterations of the language, modeled on Perl's hashtable/object behaviour. In these very early versions, hashtables were written as @{
one => 1
two => 2
method => { ... }
} At this point, the fact that there was a .NET class underlying hashtables was not really relevant (hence the hiding of the .NET properties). Hashtables were pseudo-objects which included "methods": assigning a scriptblock to a key allowed you to invoke that key as |
Thanks for giving us the history, @BrucePay.
Unfortunately, that still makes it an inconsistency that can trip people up, because conceptually these things are similar. With a commitment to backward compatibility, there is no good solution. Yes, the workaround is simple, but it being obscure is bad enough in itself. For member enumeration, the proposed |
@BrucePay it would be a 'significant breaking change' to reverse the logic in the case of a small handful of properties that are attached to hashtables? That doesn't strike me as particularly significant. I'm not suggesting removing the property->key mapping, I'm suggesting querying the object's actual properties first, in the way that is likely to be expected by anyone who knows the barest basics of hashtables. I'm suggesting that because we have the native key access syntax, we can just ensure properties are queried first when using the syntax that is designed to access properties, so if there is an overlap like this (property with the same name as a key), said property is not hidden. Accessing the key itself would simply be done by using the standard collection accessor Unless you make extensive use of the present state of things, where you deliberately hide the hashtable properties with keys, it would break... Absolutely nothing, no? Using it for non-colliding key names would still work just fine, and if you (foolishly, perhaps) had some code where you took user input to insert keys to a hashtable, the possibility of them breaking your code if you don't know about the broken behaviour is quietly removed, letting you enumerate keys as per normal. |
Good point about index notation being an unambiguous way to target entries, @vexx32. While I too wish we could change the current logic, I think the backward-compatibility problem is more serious than you think:
In the context of PowerShell, you may never need to access any of a hashtable's properties from your code, which means existing code may live happily - without symptoms - with hashtables such as the following: $ht = @{ Values = 'values'; Keys = 'keys'; Count = 'chocula' } Only if the code uses dot notation and expects it to give precedence to the hashtable's own properties do you have a problem, and that code would currently be broken. Conversely, someone using Someone who knows that dot notation targets entries first would probably not construct such a hashtable (though may still be given one), but given that we're discussing this only now, the behavior is probably not widely known - and one of the nice things about PowerShell is that you don't have to be intimately familiar with the underlying .NET types. Ultimately, only a dedicated entry-accessor syntax form solves the problem - which we do have in You could argue that dot notation should never have been implemented for hashtable-entry access and member enumeration, but those ships have clearly sailed, and the flip sides are convenience and familiarity. The member-enumeration case is less problematic, because it does give precedence to the list's own properties (and you can use enumeration to ensure that you're targeting entries), but it sounds like we'll have to live the |
…erminstic PowerShell syntactic sugar behavior for keyed collections: PowerShell/PowerShell#7758
What a surprise in a bad way -- I can't believe the language would do something like this. I filed a doc bug to make this more visible, we probably need to add any property accessors like Languages should not have non-deterministic behavior, especially if it's not documented. At this point I understand the arguments about not just "fixing" it due to the fix itself breaking code, but if we can't invent a mode called "don't alter the behavior of .net types at runtime", then at the very least let's identify a syntax for accessing collections without strange workarounds. If I add |
Another option is to create a |
@PowerShell/powershell-committee
@rjmholt (I can't tag them, apparently, heh!~)
Per discourse in #7736, opening this for hashtable key > property precedence and dynamic binding issues.
Steps to reproduce
Expected behavior
When accessing .Keys property, the keys of the hashtable should be listed. Properties (statically-bound, part of the parent object) should have higher precedence than keys in the hashtable, which are d
Hashtable keys should be lower precedence, because the native key access syntax
$Hash['Keys']
is already an alternative and should be preferred in most cases regardless. The key->dot-property mapping is syntactic sugar and should not override actual object properties.Actual behavior
The key named 'keys' is accessed instead, preventing listing of the hashtable keys without some trickery in amongst
.PSObject.Properties
This behaviour is reflected the same way for all hashtable object properties -- specifying a key in the table that has the same name as a property will mask the property and make it inaccessible, with the sole exception of the hidden
.psobject
property.Environment data
The text was updated successfully, but these errors were encountered: