如何定义一个位组合的类型?

huangapple go评论62阅读模式
英文:

How to define a type of a bit-combination?

问题

我正在努力使用PowerShell创建一个具有类似文件属性的位组合的自定义类型。稍后,该类型的使用应该像这样工作:

$attr = [myType]::new()
$attr.read = $true
$attr.write = $true
$attr.execute = $true
write-host $attr # 或者 $attr.toString()? -> read,write,execute
write-host $attr.value__ # -> 7 (3位设置为1)

我的最终类型将需要6位。我希望在以后的代码中跳过手动位操作的部分,以便获取每个位。因此,如果可能的话,我希望在类型中实现它。有关如何完成这个任务的任何想法吗?

英文:

I am struggling with Powershell to create a custom type that has a bit-combination like file-attributes. The usage of the type should work later like this:

$attr = [myType]::new()
$attr.read = $true
$attr.write = $true
$attr.execute = $true
write-host $attr # or $attr.toString()? -> read,write,execute
write-host $attr.value__ # -> 7 (3 bits set to 1)

My final type will need 6 bits. I want to skip the part with manual bit-operations in my later code to get each bit back. So, I want to have it in the type, if possible. Any ideas how to get this done?

答案1

得分: 3

为此,您可以使用PowerShell的枚举作为标志功能:

> ## 枚举作为标志
> 枚举可以定义为一组位标志的集合。 在任何给定点,枚举表示这些标志中的一个或多个打开状态。
>
> 要使枚举作为标志正常工作,每个标签应该具有二的幂值。

适用于您问题的示例

在以下示例中创建了Access枚举

[Flags()] enum Access {
    Execute = 1
    Write = 2
    Read = 4
}

利用PowerShell隐式类型转换的优势,其中通常左操作数决定右操作数的类型转换(尊重运算符优先级),您可以如下使用enum标志:

分配

要向[Access]类型分配位(标志),您可以使用简单的字符串数组:

$Access = [Access]'Read', 'Execute'

或者由@mklement0评论的,使用单个字符串:

$Access = [Access]'Read, Execute'

阅读

要读取(和/或显示)分配的访问:

$Access
Execute, Read

[int]$Access
5

设置

要设置[Access]类型的位(标志),您可以使用二进制或(-bor)运算符:

$Access -bor 'Write'
Execute, Write, Read

重置

要重置[Access]类型的位(标志),您可以使用二进制与(-band)和二进制反转器(-bnot)运算符:

$Access -band -bnot [Access]'Read'
Execute

<sup>(请注意,您需要显式设置-not运算符的RHS类型)</sup>

测试

要测试特定位是否已设置,可以使用二进制比较运算符-band。 在此示例中,我们测试$Access值中的[Access]属性。

If ($Access -band 'Read') { 'You have read access' }
'You have read access'

@mclayton所指出,这对于一次多个标志将不起作用:

$Access -band ([Access]'read, write')
Read

返回Read,它隐式转换为$True,请参阅:布尔\从集合类型转换
换句话说,如果您想确保$Access值中设置了所有相关位(标志),您可能想使用HasFlag方法:

$Access.HasFlag([Access]'read, write')
False

感谢@mklement0列出了与枚举相关的值得注意的GitHub问题(截至PowerShell 7.4.0-preview.3):

英文:

For this you might use the PowerShell Enumerations as flags feature:

> ## Enumerations as flags
> Enumerations can be defined as a collection of bit flags. Where, at any given point the enumeration represents one or more of those flags turned on.
>
> For enumerations as flags to work properly, each label should have a power of two value.

Example specific to your question

In the following example the Access enumeration is created

[Flags()] enum Access {
    Execute = 1
    Write = 2
    Read = 4
}

Taking advantage of the PowerShell implicit type casting where generally the left-hand-side of the operator dictates the type casting of the right-hand-side (respecting the operator precedence) you might use the flag enum as follows:

Assigning

To assign bits (flags) to the [Access] type, you might use a simple string array:

$Access = [Access]&#39;Read&#39;, &#39;Execute&#39;

Or as commented by @mklement0, use a single string:

$Access = [Access]&#39;Read, Execute&#39;

Reading

To read (and/or display) the assigned access:

$Access
Execute, Read

[int]$Access
5

Setting

To set a bit (flag) of the [Access] type, you might use the binary or (-bor) operator:

$Access -bor &#39;Write&#39;
Execute, Write, Read

Resetting

To reset a bit (flag) of the [Access] type, you might use the binary and (-band) and a binary invertor (-bnot) operator:

$Access -band -bnot [Access]&#39;Read&#39;
Execute

<sup>(note that you will need to explicitly set the type for RHS of the -not operator)</sup>

Testing

To test that a specific bit is set, you can use the binary comparison operator -band. In this example, we test for the [Access] attributes in the value of $Access.

If ($Access -band &#39;Read&#39;) { &#39;You have read access&#39; }
&#39;You have read access&#39;

As noted by @mclayton this will not work for multiple flags in once:

$Access -band ([Access]&#39;read, write&#39;)
Read

Returns Read which implicitly casts to $True, see: Booleans\Converting from collection types.
In other words, if you want to make sure that all concerned bits (flags) are set in the $Access Value, you probably want to use the HasFlag method instead:

$Access.HasFlag([Access]&#39;read, write&#39;)
False

Thank you @mklement0 for the list of notable enum-relevant GitHub issues (as of PowerShell 7.4.0-preview.3):

huangapple
  • 本文由 发表于 2023年5月6日 16:47:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76187970.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定