1

I am very confused. I'm used to in most programming languages to where referencing a property in the dot notation (e.g. $object.AProperty) is the exact same thing as referencing it in what I'll call the "hashtable" notation (e.g. $object['code']).

However, I've got an Invoke-RestMethod request that is returning content from a page. If in debugging I output: $Object['code']

I get $null

And yet, if I output: $Object.code

I get the value that is actually within it, which is "200".

Why on earth would this happen?

I can work past this issue by using the other notation, but I'm so confused as to why it happens. I was surprised to find that in PowerShell, even the following is proper: $Object.$property

As a result, this is a non-issue for my code, but I'd like to understand what is happening.

Doug
  • 6,446
  • 9
  • 74
  • 107
  • 3
    In powershell, hashtables are objects, but not all objects are hashtables. The two notations are only interchangeable for actual hashtables; for non-hashtables, you must use dot notation. – Jeff Zeitlin Aug 22 '22 at 17:59
  • 1
    You should post this as an answer. So, you're saying for non-hashtable objects, the ONLY way to access the properties is with the dot notation? Very interesting! – Doug Aug 22 '22 at 18:02
  • 1
    Yes, but you can do `$object.$propertyName` if property name is dynamic (as you already noted). – zett42 Aug 22 '22 at 18:11
  • 1
    The difference is more obvious if you enable strict mode (```Set-StrictMode -Version "Latest"```) - then ```$Object['code']``` would throw an exception ```InvalidOperation: Unable to index into an object of type "System.Management.Automation.PSObject".```. When Strict Mode is Off PowerShell swallows this exception (or maybe just doesn't raise it in the first place) and returns ```$null``` instead. However, for hashtables, it's legitimate to invoke an indexer, but it's up to the underlying .net class to worry about what happens if the specified key doesn't exist... – mclayton Aug 22 '22 at 18:41
  • 2
    There is some good info [here](https://stackoverflow.com/a/68928211/7571258). I just found another way to access properties, that is using expressions, e. g. `$object.('c0de' -replace '0','o')` – zett42 Aug 22 '22 at 18:46
  • 1
    @zett42 - you can also do, e.g. ```$object."my property name"``` (which I guess is really just a simple form of your example with an expression) - it's useful if a ```pscustomobject``` has a property with special characters that the parser would otherwise not handle properly. – mclayton Aug 22 '22 at 18:50

1 Answers1

2

As I wrote in the comment, hashtables are objects, but not all objects are hashtables. In Powershell, you can only use hashtable notation on objects that are actually hashtables; for everything else, you must use dot notation. Generally, using hashtable notation on a non-hashtable will return a null value rather than throwing an error; if you want to force an error to be thrown, you should Set-Strictmode -Version "Latest", which will enforce the tightest interpretation of Powershell rules (such as this, or setting a variable before referencing the value). Note that in both dot notation and hashtable notation, the index/member name can be generated by an expression, but for a non-hashtable, an error will be thrown if the expression does not evaluate to the name of an existing member.

Jeff Zeitlin
  • 9,773
  • 2
  • 21
  • 33
  • 1
    Nicely done. Worth noting that `Set-StrictMode -Version Latest` is ill-advised in _production_ code, as it could break code if additional checks are introduced in later PowerShell versions. To prevent inapplicable use of string index expressions, `Set-StrictMode -Version 2` or higher can be used. – mklement0 Aug 22 '22 at 20:14