Различаются guish различные виды хеш-таблиц в PowerShell? - PullRequest
4 голосов
/ 08 марта 2020

Похоже, что в PowerShell есть разные типы хеш-таблиц, которые чувствительны к регистру, а какие нет. При определении хеш-таблицы как следующей она не чувствительна к регистру :

$ht = @{ "Test" = "HI" }

$ht.Contains("test") #returns true, even with key name lowercase
True

$ht.ContainsKey("test") #returns true, even with key name lowercase
True

$ht.GetType()

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

Однако, если вы определите ее как таковую , она будет чувствительна к регистру :

$ht_caseSensitive = New-Object System.Collections.Hashtable
$ht_caseSensitive.Add("Test", "HI")

$ht_caseSensitive.Contains("test") # returns false, since it's all lowercase
False

$ht_caseSensitive.ContainsKey("test") # returns false, same with contains key function
False

$ht_caseSensitive.GetType()

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

Однако, как показано в выводе GetType(), я не могу найти способ провести различие между этими объектами.

  • Почему один регистр чувствителен, а другой нет?
  • Можно ли как-то отличить их, когда важно знать, имею ли я дело с хеш-таблицей, чувствительной к регистру или нет?

1 Ответ

5 голосов
/ 09 марта 2020

Почему один регистр чувствителен, а другой нет?

Поскольку PowerShell часто намеренно изменяет значение по умолчанию. NET функциональность, чтобы регистр- нечувствителен в соответствии с PowerShell без учета регистра в целом .

  • Следовательно, в то время как hashtable литерал @{ "Test" = "HI" } действительно создает экземпляр [hashtable] (System.Collections.Hashtable), PowerShell создает его с явно выраженным регистром-НЕИЗВЕСТНЫМ компаратором равенства за кадром. [1]

  • Напротив, конструирует a [hashtable] экземпляр напрямую соблюдает . NET значения по умолчанию, который должен просто вызывать метод .Equals() для поиска ключей, который в случае string keys (типичный случай) составляет порядковый номер, case-SENSITIVE сравнение.


Могу ли я как-то различать их, когда важно знать, восстановление с помощью хеш-таблицы, чувствительной к регистру или нет?

Если вы всегда используете хеш-таблицу PowerShell литералы и / или создаете (инициализируете) хеш-таблицы через литерал @{}, вы всегда будете получать регистр нечувствительных поисков.


В случае, если вам все еще нужно поразмышлять над данным экземпляром [hashtable], чтобы определить, его равенство равенства учитывает регистр или нет, вы можете использовать следующую - неясную - технику:

# Create a case-SENSITIVE hashtable.
# Note: in PowerShell v5+, the more efficient alternative is: 
#       $someHashTable = [hashtable]::new()
$someHashTable = New-Object hashtable # System.Collections.Hashtable

# Use reflection to get the *non-public* (protected, in this case)
# .EqualityComparer property value.
$equalityComparer = [hashtable].GetProperty(
   'EqualityComparer',
   [System.Reflection.BindingFlags]'NonPublic, Instance'
 ).GetValue($someHashTable)

# The hashtable is case-sensitive if it either doesn't define
# an explicit comparer or uses one that is case-sensitive.
$isCaseSensitive = $null -eq $equalityComparer -or 
                   0 -ne $equalityComparer.Compare('a', 'A')

[1] в Windows PowerShell ( версии до v5.1), этот компаратор был - удивительно - чувствительный к культуре ; в PowerShell [Core] начиная с v7.0 он использует порядковый номер (но все еще без учета регистра) сравнения. Обратите внимание, что во многих других контекстах PowerShell использует инвариантное к культуре поведение вместо этого - см. этот ответ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...