4

I have a foreach loop that currently puts three entries in my hashtable:

$result = foreach($key in $serverSpace.Keys){
    if($serverSpace[$key] -lt 80){
        [pscustomobject]@{
            Server = $key
            Space = $serverSpace[$key]}}}

When I use

$result.count

I get 3 as expected. I changed the foreach loop to exlude the entries less than or equal to one using

$result = foreach($key in $serverSpace.Keys){
    if($serverSpace[$key] -lt 80 -and $serverSpace[$key] -gt 1){
        [pscustomobject]@{
            Server = $key
            Space = $serverSpace[$key]}}}

$result.count should have 1 as its output but it doesn't recognize .count as a suggested command and $result.count doesn't output anything anymore. I'm assuming when theres only one entry in the hash table it won't allow a count? Not sure whats going on but my conditions for my script are dependent on the count of $result. Any help would be appreciated.

5
  • 2
    Force it to be an array: @($result).count Commented Jul 12, 2021 at 15:28
  • 1
    [1] that PSCO is NOT a hashtable. [grin] [2] if you want a single object to have a .Count property, you need to make that object into a collection. the easiest way is to prefix the $Var name with [array]. Commented Jul 12, 2021 at 15:29
  • Oh wow I'm dumb. That makes sense. Thank you to both of you Commented Jul 12, 2021 at 15:32
  • Does this answer your question? Powershell being too clever Commented Jul 12, 2021 at 16:12
  • Terminology note: What your foreach loop is returning is one or more custom objects ([pscustomobject] instances), not hashtables. Commented Jul 13, 2021 at 2:37

2 Answers 2

2

$result is not a hashtable so I prefixed it with @($result).count. Thank you to @Theo and @Lee_Dailey

Sign up to request clarification or add additional context in comments.

Comments

2

What you're seeing is a bug in Windows PowerShell (as of the latest and final version, 5.1), which has since been corrected in PowerShell (Core) 7 - see GitHub issue #3671 for the original bug report.

That is, since v3 all objects should have an intrinsic .Count property, not just collections, in the interest of unified treatment of scalars and collections - see this answer for more information.

The workaround for Windows PowerShell is indeed to force a value to be an array via @(...), the array-subexpression operator, which is guaranteed to have a .Count property, as shown in your answer, but it shouldn't be necessary and indeed isn't anymore in PowerShell (Core) 7.

# !! Due to a BUG, this outputs $null in *Windows PowerShell*,
# !! but correctly outputs 1 in PowerShell (Core) 7.
([pscustomobject] @{}).Count

# WORKAROUND for Windows PowerShell, effective in *both* editions.
# However, note that this comes at a cost: if what is inside @(...)
# is already a collection (enumerable), it will be
# *enumerated and collected in a new array*, which is inefficient.
@([pscustomobject] @{}).Count

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.