37

I have been pushing into the .NET framework in PowerShell, and I have hit something that I don't understand. This works fine:

$foo = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$foo.Add("FOO", "BAR")
$foo

Key                                                         Value
---                                                         -----
FOO                                                         BAR

This however does not:

$bar = New-Object "System.Collections.Generic.SortedDictionary``2[System.String,System.String]"
New-Object : Cannot find type [System.Collections.Generic.SortedDictionary`2[System.String,System.String]]: make sure t
he assembly containing this type is loaded.
At line:1 char:18
+ $bar = New-Object <<<< "System.Collections.Generic.SortedDictionary``2[System.String,System.String]"

They are both in the same assembly, so what am I missing?

As was pointed out in the answers, this is pretty much only an issue with PowerShell v1.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
EBGreen
  • 36,735
  • 12
  • 65
  • 85

3 Answers3

83

In PowerShell 2.0 the new way to create a Dictionary is:

$object = New-Object 'system.collections.generic.dictionary[string,int]'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ShanePowser
  • 831
  • 1
  • 6
  • 3
  • 7
    It's true that it is a much better answer. **If** the user is on v2. The question was asked with regard to v1 though. There are still a large number of people in the world that are on v1 as well. – EBGreen Jul 14 '11 at 14:28
  • Obviously, you will have the same problem in v2 if one of the types is declared in a 3rd party assembly: http://stackoverflow.com/questions/11975130. This seems to be fixed in v4 – marsze Apr 14 '16 at 08:37
20

Dictionary<K,V> is not defined in the same assembly as SortedDictionary<K,V>. One is in mscorlib and the other in system.dll.

Therein lies the problem. The current behavior in PowerShell is that when resolving the generic parameters specified, if the types are not fully qualified type names, it sort of assumes that they are in the same assembly as the generic type you're trying to instantiate.

In this case, it means it's looking for System.String in System.dll, and not in mscorlib, so it fails.

The solution is to specify the fully qualified assembly name for the generic parameter types. It's extremely ugly, but works:

$bar = new-object "System.Collections.Generic.Dictionary``2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tomasr
  • 13,683
  • 3
  • 38
  • 30
  • 1
    Is there any reference that describes this syntax? I'm trying to implement BeginInvoke from a Powershell object and having a heck of a time with using the input and output parameters in one of the overloads for it. I just can't seem to get the declaration right. – Tom H Jun 13 '12 at 18:05
4

There are some issues with Generics in PowerShell. Lee Holmes, a dev on the PowerShell team posted this script to create Generics.

Steven Murawski
  • 10,959
  • 41
  • 53