1

I am refactoring some old(ish) code, and I have used two approaches for creating some arrays and ordered dictionaries, for example...

[Collections.Specialized.OrderedDictionary]@{}

and

New-Object Collections.Specialized.OrderedDictionary

I wonder which of these two approaches to instantiating arrays and hashtables/dictionaries is better? FWIW, I need code that that is version agnostic from PS2.0 thru current. Performance is a secondary concern.

FWIW, it looks like the former is MUCH better from a performance standpoint. I tried

Measure-Command {
    foreach ($i in 1..10000) {
        $array1 = [Collections.Specialized.OrderedDictionary]@{}
    }
}
Measure-Command {
    foreach ($i in 1..10000) {
        $array2 = New-Object Collections.Specialized.OrderedDictionary
    }
}

and got 34 milliseconds vs 278 milliseconds. Of course I am not creating 10K instances, nor is performance the main priority, not is 278 milliseconds poor performance even if that was a priority. But it sure shows there is a big difference in the process, even if the end result is actually the same.

Gordon
  • 6,257
  • 6
  • 36
  • 89
  • So it's a typecast vs. new-object… See also [here](https://stackoverflow.com/questions/5064534/does-casting-create-new-object)... – Peter Schneider Nov 03 '18 at 17:33
  • It seems odd that you'd compare the two by measuring the time it takes to create 10,000 empty instances of each object. Wouldn't a relevant test (I'm assuming you don't really need to create 10,000 instances of an empty object) be to create two objects using the two approaches and then load each of them with 10,000 data items? I did this (I updated my answer below), ran it repeatedly and observed that sometimes array1 took longer to load, sometimes array2 took longer to load (both around 500 ms on my machine), but the load times were within 3%-4% of each other. – VA systems engineer Nov 04 '18 at 12:08
  • @Nova Sys Eng, indeed my example is not real world at all, more just demonstrating to myself that at some level the two approaches are different, even though the final result is the same. What is interesting is that I hadn't tested this in PS2.0 yet, and in fact only the New-Object approach works with ordered dictionaries. You can't cast a hash table to an ordered dictionary in PS2.0, but you can in later versions. And you can cast an array to an array list in any version. So I guess I have my answer, based solely on PS version portability. – Gordon Nov 04 '18 at 12:45

1 Answers1

0

When I do the following:

cls

write-host "array1:"
$array1 = [System.Collections.Specialized.OrderedDictionary]@{}
$array1.GetType()
(Measure-Command -Expression {1..10000 | ForEach-Object { $array1.Add($_,"") }}).Milliseconds

write-host
write-host

write-host "array2:"
$array2 = New-Object System.Collections.Specialized.OrderedDictionary
$array2.GetType()
(Measure-Command -Expression {1..10000 | ForEach-Object { $array2.Add($_,"") }}).Milliseconds

I get, e.g., the following, i.e., I think they are the same type so I wouldn't expect any difference, performance or otherwise:

array1:

IsPublic IsSerial Name              BaseType     
-------- -------- ----              --------     
True     True     OrderedDictionary System.Object
492


array2:

IsPublic IsSerial Name              BaseType     
-------- -------- ----              --------     
True     True     OrderedDictionary System.Object
500        

BTW, as of PS 3.0, $array3=[ordered]@{} gives you the same type+++:

array3

IsPublic IsSerial Name              BaseType     
-------- -------- ----              --------     
True     True     OrderedDictionary System.Object                                                                                                 

+++ About Hash Tables

Beginning in PowerShell 3.0, you can use the [ordered] attribute to create an ordered dictionary (System.Collections.Specialized.OrderedDictionary) in PowerShell.

VA systems engineer
  • 2,856
  • 2
  • 14
  • 38
  • Indeed, I know the end result is the same, I am curious if there is a reason to use one over the other to get to the same end result? Much like $array.Add() and $array += $array end up with the same result, but there is a huge difference in performance between the two. I also know I can use [ordered] in PS3.0 and later, but as I said, I have to support PS2.0 so I can't use that approach. – Gordon Nov 03 '18 at 18:40
  • I guess you need to be more specific regarding what kind of reason you're looking for. You've said performance is not the concern. What is the concern? Your original question uses different syntactical methods that produce an object of the same datatype. Unlike using `.Add` on a `Collection` and `+=` on an `Array` (different types), why would operations on two objects of the same datatype be different? I don't think they will. You ask `Which is better?` I think the answer is `They are the same` – VA systems engineer Nov 04 '18 at 12:16
  • I don't have a particular concern, I am wondering if I SHOULD and I just don't know it. Similar to what I learned about two different ways to do an array in this thread some time ago. https://stackoverflow.com/questions/46115019/generic-list-in-a-hash-table – Gordon Nov 04 '18 at 12:34