PowerShell icon indicating copy to clipboard operation
PowerShell copied to clipboard

Improve `OrderedHashtable` integration

Open iRon7 opened this issue 1 year ago • 3 comments

Summary of the new feature / enhancement

The new System.Management.Automation.OrderedHashtable class is a great step forward in moving to a dictionary that is ordered by default. Therefore I wouldn't be surprised that this System.Management.Automation.OrderedHashtable class would eventually replace the System.Collections.Specialized.OrderedDictionary class.

For this to happen, I would like to able to use the same syntactic sugars as with the Hashtable/Ordered type:

  • Preserve the hash literal node order Currently this doesn't work as expected (like it does for [PSCustomObject] and [Ordered]):
[System.Management.Automation.OrderedHashtable]@{ One = 1; Two = 2; Three = 3; Four = 4 }

Name                           Value
----                           -----
Two                            2
Four                           4
One                            1
Three                          3

Side note: unlike the OrderedDictionary class, I think it is ok that the OrderedDictionary is able to cast from an unordered (non-literal) hash table (assuming that it will be documented that the order is already decayed in this matter):

$Hashtable = @{ One = 1; Two = 2; Three = 3; Four = 4 }
[System.Management.Automation.OrderedHashtable]$HashTable
  • Ability to use the friendly name to cast As with the [Ordered] (and [HashTable]) type, I would like to be able to use it friendly name:
[OrderedHashtable]@{ One = 1; Two = 2; Three = 3; Four = 4 }
  • ability to compare with its friendly name As with the [Ordered] type (see: #10513), I would like to be able to use its friendly name for the -is comparison:
$OrderedHashtable = [System.Management.Automation.OrderedHashtable]@{ One = 1; Two = 2; Three = 3; Four = 4 }
$OrderedHashtable -is [OrderedHashtable]
  • Also, I would expect it somehow (pretend) to be derived from the OrderedDictionary class Currently the following returns False, where I would like to see it True so that doesn't break scripts that test for an OrderedDictionary type:
$OrderedHashtable = [System.Management.Automation.OrderedHashtable]@{ One = 1; Two = 2; Three = 3; Four = 4 }
$OrderedHashtable -is [Ordered]
False # Expected (wishful thinking) True

Related: #19073

iRon7 avatar Feb 15 '23 09:02 iRon7

The issue you link to:

  • https://github.com/PowerShell/PowerShell/issues/19073

would give you most of what you want implicitly, so do you have specific concerns about that proposal that would call for what you're proposing here instead?

If #19073 is implemented, you'd simply get ordered hashtables by default.

A [OrderedHashtable] type accelerator would then only be needed for -is [OrderedHashtable] or - hypothetically for now, because no such constructor overload exists - for creating case-sensitive hash tables, e.g. [OrderedHashtable]::new([System.StringComparer]::InvariantCulture)).

I would expect it somehow (pretend) to be derived from the OrderedDictionary class

I don't think such a "white lie" is a good idea, as it can create confusion, and there may be cases where you do want to distinguish [ordered] from [OrderedHashtable].

If you really need to know whether a preexisting instance maintains definition order, which doesn't strike me as a common use case,$ht -is [ordered] -or $ht -is [OrderedHashtable] isn't too much of a hardship.

Therefore I wouldn't be surprised that this System.Management.Automation.OrderedHashtable class would eventually replace the System.Collections.Specialized.OrderedDictionary class.

#19073 would allow for that, with the only change of habit required from users is to apply the positional indexing to the .Values property instead of directly to the hashtable. ($oht = @{ foo = 'one'; bar = 'two' }; $oht.Values[1] (doesn't currently work) instead of $oht = [ordered] @{ foo = 'one'; bar = 'two' }; $oht[1] (in v7.3+, .Values[1] works with [ordered] too, thanks to your own efforts.)

Cross-edition code will be stuck with [ordered].

mklement0 avatar Feb 16 '23 20:02 mklement0

[ordered] is a type accelerator to OrderedDictionary so changing that would be a big breaking change. We could certainly add a type accelerator for [orderedhashtable] which wouldn't be a breaking change, but the implicit idea from @mklement0 is probably a better choice that would resolve many of these issues if accepted.

SteveL-MSFT avatar Mar 13 '23 20:03 SteveL-MSFT

As much as I still love the idea of making hashtable literals uses OrderedDictionary by default, running some benchmarks has convinced me that this isn't feasible due to backward compatibility concerns, after all: programmatic construction of (larger) OrderedDictionary instances is substantially slower than with [hashtable] (and also uses more memory).

  • see https://github.com/PowerShell/PowerShell/issues/19073#issuecomment-1476750522.

I have therefore closed #19073.

mklement0 avatar Mar 20 '23 18:03 mklement0

Please triage this issue and either mark it with something like Resolution-Declined or put it on a kind of wishlist "Issue we would like to prioritize, but we can't commit we will get to it yet"

iRon7 avatar Nov 15 '23 08:11 iRon7