Powershell 为什么不能将字符串指定给强类型布尔变量?
假设我尝试将字符串分配给强类型整数变量:Powershell 为什么不能将字符串指定给强类型布尔变量?,powershell,Powershell,假设我尝试将字符串分配给强类型整数变量: [int]$bar = '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能够将字符串'1'转换为整数 现在
[int]$bar = '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能够将字符串'1'
转换为整数
现在,如果我尝试对强类型布尔变量执行相同操作,情况就不同了:
[int]$bar = '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
有人知道这种看似不一致的行为的原因吗?实用建议:
在大多数情况下,我会讨论以下方法,而不是类型化变量:在赋值之前将值转换为目标类型,然后让类型系统推断变量类型:
$foo = [bool]"foo"
$foo = "foo" -as [bool]
$foo = $true -eq "foo"
当前的问题是: (这不是权威答案,而是最佳猜测) 在
关于变量的帮助文件中简要提到:
变量类型
可以在变量[…]中存储任何类型的对象
Windows PowerShell变量是“松散类型”,这意味着
它们不限于特定类型的对象。[……]
[…关于值推断类型的部分bla bla bla…]
您可以使用类型属性和强制转换符号来确保
变量只能包含指定类型的一个或多个对象
可以转换为该类型的。如果您尝试分配一个值
对于另一种类型,Windows PowerShell尝试将该值转换为
它的类型。如果不能,赋值语句将失败
若要使用强制转换表示法,请在
变量名(位于赋值语句的左侧)
虽然文档中没有使用“类型属性”和仅在赋值过程中应用的独特约束,但(至少对我来说)表明这是显式转换的特例
这意味着什么?
当您在赋值期间向变量添加显式强制转换表示法时,如上所述,PowerShell会向变量添加一个ArgumentTypeConverterAttribute
,并且PowerShell会突然被特定于类型的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
转换比普通转换“魔法”限制更大:
同样,在这种类型的转换中,布尔参数只接受布尔值和数字,例如$True、$False、1或0。,而powershell本身通常在隐式转换为[bool]
时将任何非空、非零或非空值解释为$True
换言之:
强制转换符号与上下文相关:
即使它们看起来完全一样如果尝试执行$foo='foo',然后执行[boolean]$foo会发生什么?错误消息完全有效,因为我们知道bools可以是1或0。现在,对于第二个代码段,PS似乎正在返回对字符串长度的检查。对空字符串的强制转换返回false
,否则每当字符串的长度>=1时,其true
。原因是“设计就是这样”。另请参见一个类似的问题@SzabolcsPáll这当然有效,因为[boolean]$foo
也是一个显式转换。我的猜测是,在[boolean]$foo='foo'中,实际转换是由赋值运算符进行的,该运算符不使用tobolean/Parse,而是使用另一个不接受字符串的函数来转换它。任何人都可以证明/反驳它?这是一个很好的解释,说明了当“错误”类型的值分配给强类型变量时会发生什么。与“普通”类型转换魔法相比,这会导致不同的施法行为,这仍然很奇怪。但是这个问题回答得很好。我想“强类型”语法重用了C#/.NET CTS中的转换规则,以避免重新实现自身使用。这也将为来自其他.NET语言的开发人员提供一些一致性