为什么不能将字符串赋值给强类型的布尔变量?

时间:2015-08-28 13:31:08

标签: powershell

假设我尝试将字符串分配给强类型的整数变量:

[int]$bar = '1'

这很有效,因为PowerShell能够将字符串'1'强制转换为整数。

现在情况有所不同,如果我尝试使用强类型布尔变量:

[boolean]$foo = 'foo'
Cannot convert value "System.String" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 
or 0.

我发现这令人困惑,因为PowerShell同时允许从字符串显式转换为布尔值:

[boolean]'foo'
True

有谁知道这种看似不一致行为的原因?

1 个答案:

答案 0 :(得分:4)

实用建议:

在大多数情况下,我会争论以下方法,而不是键入变量:在赋值之前将转换为目标类型,然后让类型系统推断变量类型:

$foo = [bool]"foo"
$foo = "foo" -as [bool]
$foo = $true -eq "foo"

手头的问题:

(这不是一个权威的答案,但最好的猜测)

about_Variables帮助文件中简要提及:

  

变量类型

     

您可以将任何类型的对象存储在变量[...]

中      

Windows PowerShell变量是“松散类型”,这意味着      它们不限于特定类型的对象。 [...]

     

[...关于价值推断类型的部分bla bla bla ...]

     

您可以使用类型属性并使用强制转换符号来确保a      变量只能包含指定类型或对象的对象      可以转换为该类型。如果您尝试分配值      在另一种类型中,Windows PowerShell尝试将值转换为      它的类型。如果不能,则赋值语句失败。

     

要使用强制表示法,请在之前输入括在括号中的类型名称      变量名称(在赋值语句的左侧)。

虽然“type attribute”和仅在赋值期间适用的不同约束在文档中没有使用,但(至少对我来说)表明这是显式转换的特例。

这意味着什么?

变量中添加显式强制转换表示法时,如上所述,PowerShell会在变量中添加ArgumentTypeConverterAttribute,并突然覆盖PowerShell的type conversion magic通过特定于类型的Transform()方法:

PS C:\> $var = 5
PS C:\> Get-Variable var |fl *


Name        : var
Description :
Value       : 5
Visibility  : Public
Module      :
ModuleName  :
Options     : None
Attributes  : {}



PS C:\> [int]$var = 5
PS C:\> Get-Variable var |fl *


Name        : var
Description :
Value       : 5
Visibility  : Public
Module      :
ModuleName  :
Options     : None
Attributes  : {System.Management.Automation.ArgumentTypeConverterAttribute}

如果我们使用布尔类型重复此实验,您可以看到ArgumentTypeConverterAttribute转换比正常转换“魔法”更具限制性:

PS C:\> [bool]$foo = $true
PS C:\> (Get-Variable foo).Attributes[0].Transform($ExecutionContext,"foo")
Exception calling "Transform" with "2" argument(s): "Cannot convert value "System.String" to type "System.Boolean". Boolean parameters
accept only Boolean values and numbers, such as $True, $False, 1 or 0."
At line:1 char:1
+ (Get-Variable foo).Attributes[0].Transform($ExecutionContext,"foo")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentTransformationMetadataException

再次在这种类型的转换中布尔参数只接受布尔值和数字,例如$ True,$ False,1或0。,而powershell本身通常会解释任何非空的,非隐式转换为$true时,零或非空值为[bool]

换句话说

演员表示法是上下文相关的:

[bool]$SomeVariable = [bool]"bar"
   ^                ^   ^
   |                |   |
   |  during assignment |
This is a type attribute|
         This is a cast notation

即使他们看起来一样