Skip to content

Write-Output -NoEnumerate doesn't handle Hashtable properly #14047

@kganjam

Description

@kganjam

Steps to reproduce

$g = @{}
$g["foo"] = 1
$g["bar"] = 1
$g["foo"] # returns 1
$g."foo" # returns 1

$h = write-output $g -NoEnumerate
$h["foo"] # returns $null
$h."foo" # returns 1
$h["bar"] # returns $null
$h."bar" # returns 1
$h.count # returns 1
$($h.keys | measure).count # returns 2

$f = write-output $g
$f["foo"] # returns 1
$f."foo" # returns 1
$f["bar"] # returns 1
$f."bar" # returns 1
$f.count # returns 2

Expected behavior

$h["foo"] # returns 1
$h.count # returns 2

Actual behavior

$h["foo"] # returns $null
$h.count # returns 1

Environment data

Name                           Value
----                           -----
PSVersion                      7.1.0
PSEdition                      Core
GitCommitId                    7.1.0
OS                             Microsoft Windows 10.0.19042
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Notes

I thought I would use end { Write-Output $Result -NoEnumerate } to be safe for ConvertTo-Dictionary the way I do to ensure an empty HashSet is returned by ConvertTo-HashSet when pipeline input is empty, but it turns out you must use end { $Result } or you get back a broken Hashtable.

Maybe this is expected behavior somehow, but I don't understand what $h is and how $h."foo" and $h."bar" both work even though $h.count is 1. And why $h.keys gives 2 items, while $h.count is 1. I guess $h is being unrolled and that is how it is working. Still, not what I would have expected from -NoEnumerate.

<#
.SYNOPSIS
Convert a stream of objects to a Dictionary
.EXAMPLE
$services = Get-Service | ConvertTo-Dictionary {$_.Name} {$_.DisplayName}
#>
function ConvertTo-Dictionary {
    param(
        [ScriptBlock]$KeyExpression,
        [ScriptBlock]$ValueExpression = { $_ }
    )
    begin { $Result = @{} }
    process { $Result[(&$KeyExpression)] = (&$ValueExpression) }
    end { $Result } 
}

<#
.SYNOPSIS
Convert a stream of objects to a HashSet
.EXAMPLE
$services = get-service | select -expandproperty Name -first 10 | ConvertTo-HashSet 
$null -eq $services # False
$Services = get-service | select -expandproperty Name -first 0 | ConvertTo-HashSet 
$null -eq $services # False
#>
function ConvertTo-HashSet {
    begin { $hashSet = [System.Collections.Generic.HashSet[String]] @() }
    process {
        $hashSet.add($_) | Out-Null
    }
    end { Write-Output -NoEnumerate $hashSet }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions