I need to create a Dictionary with Tuple key in Powershell. Exactly like I can do in C# like this:
var test = new Dictionary<(int, bool), int>();
// Add
test.Add((1, false), 5);
// Get
int a = test[(1, false)];
(Taken from Hashtable with MultiDimensional Key in C#)
Is it possible? (I am running Powershell version 5.1.18362.145.)
Thanks!
To add to Jeroen Mostert's excellent comments on the question:
The following is a direct translation of your C# code to PowerShell v5.1+ code:
using namespace System.Collections.Generic
# Construct
$test = [Dictionary[[ValueTuple[int, bool]], int]]::new()
# Add
$test.Add([ValueTuple[int, bool]]::new(1, $false), 5)
# Get
$test[[ValueTuple[int, bool]]::new(1, $false)]
using namespace
is a PSv5+ feature akin to C#'s using
construct: it allows you to refer to the types in the specified namespace by their mere names, without namespace qualification.
As Jeroen points out, PowerShell has no syntactic sugar for value-tuple instances, so that C# tuple literal (1, false)
must be represented as an explicit constructor call: [ValueTuple[int, bool]]::new(1, $false)
.
Create()
method on the non-generic System.ValueType
base type, in which case the tuple component types are inferred:[ValueTuple]::Create(1, $false)
Given that PowerShell exposes a type's constructors via the static ::new()
method on the type itself, you can simplify the code by instantiating the specific tuple type once and reusing it via a variable:
using namespace System.Collections.Generic
# Instantiate the concrete tuple type (type arguments locked in).
$tupleType = [ValueTuple[int, bool]]
# Construct the dictionary with the tuple type as the key.
# See explanation below.
$test = [Dictionary`2].MakeGenericType($tupleType, [int])::new()
#`# Add
$test.Add($tupleType::new(1, $false), 5)
# Get
$test[$tupleType::new(1, $false)]
The downside is that the dictionary construction becomes more awkward, because PowerShell type literals such as [Dictionary[[ValueTuple[int, bool]], int]]
must not have non-literal components.
To work around that, System.Type.MakeGenericType()
is used to construct the closed generic type from the dynamically specified type arguments; note the need to specify the arity (`2
) of the open generic type on which .MakeGenericType()
is invoked.