3

It seems PowerShell hashtable (@{}) is map of string→string by default. But I wish that my value type is Int32 so that I could do calculation on it.

How could I specify the type information when declaring a hashtable variable?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
vik santata
  • 2,989
  • 8
  • 30
  • 52
  • 1
    If you assign the value as an int, the hashtable value is still an int: $test = @{ "myValue" = 3 }; $test.myValue | gm – Martin Brandl Jun 19 '15 at 10:32
  • 1
    Show us an example of what you are doing and we will explain it. You can have it both ways. Values can be "cast" during comparsion. It all depends on what is on the left hand side of the comparison. – Matt Jun 19 '15 at 10:34

2 Answers2

7

An alternative to Hashtable is the Dictionary which allows to explicitly specify type of key and value.

In the following, a dictionary with string key and int value will be created:

[Collections.Generic.Dictionary[string, int]] $dict = @{}
    
$dict['a'] = 42      # Ok
$dict['b'] = '42'    # Ok (implicit type conversion)
$dict['c'] = 'abc'   # Error: Cannot convert value "abc" to type "System.Int32"

Note that a Dictionary created this way has case-sensitive keys, contrary to a Hashtable, whose keys are case-insensitive.

$dict['a'] = 42
$dict['A'] = 21  # Creates a 2nd entry!

To make the Dictionary case-insensitive like a Hashtable, it must be created differently, by passing a StringComparer to the Dictionary constructor:

$dict = [Collections.Generic.Dictionary[string, int]]::new( [StringComparer]::InvariantCultureIgnoreCase )
$dict['a'] = 42
$dict['A'] = 21  # Overwrites the entry whose key is 'a'
zett42
  • 25,437
  • 3
  • 35
  • 72
5

Hashtables map keys to values. The type of the keys and values is immaterial.

PS C:\> $ht = @{}
PS C:\> $ht[1] = 'foo'
PS C:\> $ht['2'] = 42
PS C:\> $ht

Name                           Value
----                           -----
2                              42
1                              foo

PS C:\> $fmt = "{0} [{1}]`t-> {2} [{3}]"
PS C:\> $ht.Keys | % {$fmt -f $_, $_.GetType().Name, $ht[$_], $ht[$_].GetType().Name}
2 [String]      -> 42 [Int32]
1 [Int32]       -> foo [String]

If you have an integer in a string and want to assign that as an integer, you can simply cast it on assignment:

PS C:\> $ht[3] = [int]'23'
PS C:\> $ht.Keys | % {$fmt -f $_, $_.GetType().Name, $ht[$_], $ht[$_].GetType().Name}
2 [String]      -> 42 [Int32]
3 [Int32]       -> 23 [Int32]
1 [Int32]       -> foo [String]
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328