I would like to check whether a given dictionary ($Dictionary -is [System.Collections.IDictionary]
) is case sensitive?
[HashTable]
, it is described here:$Dictionary = [system.collections.generic.dictionary[string,object]]::new()
, I might simply do: $Dictionary.Comparer.Equals('A', 'a')
[Ordered]
dictionary, I have no clue...Is there a generic way to check the EqualityComparer
of an dictionary?
Or: how do I cover all dictionary flavors?
As stated in comments, and answering your question:
Is there a generic way to check the
EqualityComparer
of an dictionary?
As far as I can tell, there is not, you can do your best to keep track of how to handle each specific case, some might be via reflection like with Hashtable
or OrderedDictionary
and some might be via a public property like with Dictionary<TKey, TValue>
and other generic types but that covers only specific cases.
I believe there is no way to cover all types implementing the IDictionary
and IDictionary<TKey, TValue>
interfaces. The reflection approaches are obviously not recommended, nobody is ensuring you that those private fields or properties will change in the future.
Leaving that aside, below might help you get a better perspective on how you can approach this problem.
$supportedGenericTypes = @(
# there is no interface ensuring that a type implementing `IDictionary<TKey, TValue>`
# will have a `.Comparer` property, you will need to manually check if they actually do
# before adding them to this list
[System.Collections.Generic.Dictionary`2]
[System.Collections.Concurrent.ConcurrentDictionary`2]
[System.Collections.Generic.SortedDictionary`2]
)
[System.Collections.Generic.Dictionary[string, string]]::new(),
[ordered]@{},
@{},
[System.Collections.Concurrent.ConcurrentDictionary[string, string]]::new(),
[System.Collections.Generic.SortedDictionary[string, string]]::new() |
ForEach-Object {
$type = $_.GetType()
if ($type.IsGenericType -and $type.GetGenericTypeDefinition() -in $supportedGenericTypes) {
$comparer = $_.Comparer
# need to cover any custom type implementing `IDicitonary<TKey, TValue>` here...
}
elseif (-not $type.IsGenericType) {
$instance = $_
switch ($type) {
([System.Collections.Hashtable]) {
$comparer = [System.Collections.Hashtable].
GetField('_keycomparer', [System.Reflection.BindingFlags] 'NonPublic,Instance').
GetValue($instance)
}
([System.Collections.Specialized.OrderedDictionary]) {
$comparer = [System.Collections.Specialized.OrderedDictionary].
GetField('_comparer', [System.Reflection.BindingFlags] 'NonPublic,Instance').
GetValue($instance)
}
# need to cover any custom type implementing `IDicitonary` here...
}
}
else {
throw [System.NotImplementedException]::new()
}
[pscustomobject]@{
Type = $type
Comparer = $comparer
}
}