带点的哈希表键

Posted

技术标签:

【中文标题】带点的哈希表键【英文标题】:Hashtable key with point 【发布时间】:2020-05-31 00:25:10 【问题描述】:

如何发出带有点字符的哈希表键,例如FlatAppearance.BorderSize,以便正确?

$Button = [System.Windows.Forms.Button] @

    # This is not a valid entry
    FlatAppearance.BorderSize = 0

$Button = [System.Windows.Forms.Button] @

    # This is not a valid entry too
    "FlatAppearance.BorderSize" = 0

$Button = [System.Windows.Forms.Button] @

    # This is not a valid entry too too
    FlatAppearance = @ BorderSize = 0 

当然可以这样写

$Button = [System.Windows.Forms.Button] @
$Button.FlatAppearance.BorderSize = 0

不过,写在哈希表里面更方便。但是怎么做?谢谢

【问题讨论】:

【参考方案1】:

由于Button 类型的.FlatAppearance 属性属于FlatButtonAppearance 类型,因此在这种情况下没有好的解决方案,因为FlatButtonAppearance 类型有没有公共的、无参数的构造函数

如果是这样,您将能够编写:

using namespace System.Windows.Forms

$Button = [Button] @

    # !! This is how you would generally do it, but
    # !! IN THIS CASE IT DOESN'T WORK, due to lack of an appropriate constructor.
    FlatAppearance = [FlatButtonAppearance] @ BorderSize = 0 

上述语法类似于 C# 的 object initializer 语法,将在下一节中解释。


PowerShell 中的对象初始化语法:

对于从哈希表 (@ ... ) 或预先存在的 [pscustomobject] 实例[1]转换为类型文字 ([...]) /sup> 执行隐式构造(隐式创建实例)然后多属性初始化才能工作,必须满足以下先决条件

目标类型必须有一个构造函数(可能还有其他[2]),即:

公开 and 无参数[3]

类型的公共属性的名称必须与哈希表条目的键匹配,并且条目的值必须与目标属性具有相同或兼容的类型。

这使得 PowerShell 可以通过调用 new SomeType()(PowerShell 语法中的 [SomeType]::new())在后台创建实例,然后从同名的哈希表条目中分配公共属性的值。

注意:PowerShell v3+ 中提供的此类转换实际上是语法糖,用于使用-Property 参数调用New-Object cmdlet;只有后者在 v2 中有效。


除了查阅类型的文档之外,您还可以通过调用 PowerShell 提供的静态 ::new 方法轻松在 PowerShell 中检查类型的构造函数不带括号 (() ):

PS> [System.Windows.Forms.FlatButtonAppearance]::new
# NO OUTPUT, which means the type has no public constructors at all.

# [ProcessStartInfo] has several public constructors, among them
# a public parameterless one, so you *can* initialize it by hashtable.
PS> [System.Diagnostics.ProcessStartInfo]::new

OverloadDefinitions
-------------------
System.Diagnostics.ProcessStartInfo new()
System.Diagnostics.ProcessStartInfo new(string fileName)
System.Diagnostics.ProcessStartInfo new(string fileName, string arguments)

确定类型的公共、可写实例属性

PS> [System.Windows.Forms.FlatButtonAppearance].GetProperties('Public, Instance') | 
       ? CanWrite | Select-Object Name, PropertyType

Name               PropertyType        
----               ------------        
BorderSize         System.Int32        
BorderColor        System.Drawing.Color
CheckedBackColor   System.Drawing.Color
MouseDownBackColor System.Drawing.Color
MouseOverBackColor System.Drawing.Color

[1] 例如,这对于从 JSON 反序列化的对象很有用,这些对象变为 [pscustomobject] 实例;例如:$obj = ' "Text": "Submit" ' | ConvertFrom-Json; $button = [Button] $obj

[2] 边缘情况:不能也有具有以下参数类型之一的 single 参数公共构造函数,因为它会按原样绑定强制转换操作数:

[object] 从哈希表 (@ ... ) 投射时:[hashtable][System.Collections.IDictionary][pscustomobject] 实例投射时:[psobject][pscustomobject]

[3] 方便的是,如果你定义一个类型(类)而不声明任何构造函数,你会得到一个公共无参数的默认;例如,在以下 PowerShell 示例类中,Foo隐式提供了这样一个构造函数:class Foo [string] $Bar ; $foo = [Foo] @ Bar = 'None'

【讨论】:

以上是关于带点的哈希表键的主要内容,如果未能解决你的问题,请参考以下文章

C ++:指针作为哈希表中的键

使用整数值作为哈希表的键是多么愚蠢?

[MSTL] lc面试题 10.02. 变位词组(哈希表+排序)

哈希表的应用--回旋镖的数量

哈希表与直线点的记录--直线上最多的点数计算

[M哈希表] lc447. 回旋镖的数量(哈希表+计数)