【问题标题】:Distinguish different kinds of hashtables in PowerShell?区分 PowerShell 中不同类型的哈希表?
【发布时间】:2020-03-08 18:39:52
【问题描述】:

看起来 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() 输出所示,我似乎找不到区分这些对象的方法。

  • 为什么一种区分大小写而另一种不区分?
  • 有什么办法我 当重要的是要知道是否 我正在处理是否区分大小写的哈希表?

【问题讨论】:

  • 默认情况下 PS 哈希表不区分大小写。仅通过在您的第二个示例中定义对象或几个非常罕见的方法,例如导出/导入 xml 是否可以区分大小写。
  • 这也是一个 PSScriptAnalyzer 规则:UseLiteralInitializerForHashtable

标签: powershell hashtable


【解决方案1】:

为什么一个区分大小写而另一个不区分?

因为 PowerShell 经常有意将默认 .NET 功能修改为不区分大小写不区分大小写,以保持 PowerShell 不区分大小写总体

  • 因此,虽然 hashtable literal @{ "Test" = "HI" } 确实创建了一个 [hashtable] (System.Collections.Hashtable) 实例,但 PowerShell 使用显式构造它case-INSENSITIVE 相等比较器在幕后。[1]

  • 相比之下,构造[hashtable]实例直接尊重.NET的默认值,即简单地调用@987654327 @ 键查找方法,在 string 键的情况下(典型情况)相当于 ordinal, case-SENSITIVE 比较。


当了解我处理的哈希表是否区分大小写很重要时,有什么方法可以区分它们吗?

如果你总是使用 PowerShell 哈希表 literals 和/或构造(初始化)哈希表 via 文字 @{},你总会得到 case-不敏感查找。


如果您仍然需要反映给定的[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 的版本)中,这个比较器 - 令人惊讶的是 - 文化敏感;在 v7.0 的 PowerShell [Core] 中,它使用 ordinal(但仍然不区分大小写)比较。请注意,在许多其他情况下,PowerShell 使用 culture-invariant 行为 - 请参阅 this answer

【讨论】:

    猜你喜欢
    • 2013-07-19
    • 2016-10-14
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2014-03-27
    相关资源
    最近更新 更多