6. 转换

编辑说明

重要

Windows PowerShell 语言规范 3.0 于 2012 年 12 月发布,基于 Windows PowerShell 3.0。 此规范不反映 PowerShell 的当前状态。 没有计划更新本文档以反映当前状态。 此处提供了本文档供历史参考。

该规范文档可作为 Microsoft Word 文档从 Microsoft 下载中心获取:https://www.microsoft.com/download/details.aspx?id=36389 该 Word 文档已在此 Microsoft Learn 上转换为展示形式。 转换期间,进行了一些编辑更改,以适应 Docs 平台的格式设置。 已更正某些拼写错误和次要错误。

当某种类型的值用于需要不同类型的上下文时,将执行类型转换。 如果此类转换自动发生,则称为 隐式转换。 (一个常见的示例是,某些运算符需要转换其操作数指定的一个或多个值。允许隐式转换,前提是保留源值的感觉,例如在转换数字时不会丢失数字的精度。

强制转换运算符 (§7.2.9) 允许显式转换

下面将讨论转换,并在必要时在 §6.19中对每个运算符的说明提供补充信息。

将值显式转换为它已具有的类型不会更改该值或其表示形式。

当表达式的值绑定到某个参数时,§6.17 中介绍了手动转换的规则。

6.1 转换为 void

可以通过将任何类型的值强制转换为 void 类型来显式丢弃该值。 没有结果。

6.2 转换为布尔

将任何值转换为布尔类型的规则如下所示:

  • 数值或字符值为零时,转换为 False;非零的数值或字符值则转换为 True。
  • 空类型的值转换为假。
  • 长度为 0 的字符串转换为 False;长度 > 0 的字符串转换为 True。
  • 具有值 $true 的开关参数将转换为 True,具有值 $false 的开关参数转换为 False。
  • 所有其他非 null 引用类型值都转换为 True。

如果类型实现了 IList:

  • 如果对象的长度为 > 2,该值将转换为 True。
  • 如果对象的 Length 为 1,并且第一个元素本身不是 IList,则如果该元素的值为 true,则该值将转换为 True。
  • 否则,如果第一个元素的 Count >= 1,该值将转换为 True。
  • 否则,该值将转换为 False。

6.3 转换为 char

将任何值转换为类型 char 的规则如下所示:

  • 布尔、小数、浮点数或双标量类型的值的转换出错。
  • null 类型的值将转换为 null (U+0000) 字符。
  • 一个整数类型值,如果其值可以用 char 类型表示,则该整数取该值,否则转换出错。
  • 长度不是 1 的字符串值在转换时出错。
  • 长度为 1 的字符串值转换为具有该字符值的字符。
  • 一个数值类型值,其舍入任何小数部分后的值可以在目标类型中表示该舍入值;否则,转换出错。
  • 对于其他引用类型值,如果引用类型支持此类转换,则使用该转换;否则,转换出错。

6.4 转换为整数

将任何值转换为字节、int 或 long 类型的规则如下所示:

  • 布尔值 False 转换为零;布尔值 True 转换为 1。
  • 一个字符类型的值,如果其值可以在目标类型中表示,则采用该值;否则,转换会出错。
  • 一个数值类型值,其舍入任何小数部分后的值可以在目标类型中表示该舍入值;否则,转换出错。
  • null 类型的值转换为零。
  • §6.16中所述,一个表示数字的字符串被转换。 如果在截断小数部分后,结果可以用目标类型表示,则该字符串格式正确,并且具有目标类型;否则,转换出错。 如果字符串不表示数字,则转换出错。
  • 对于其他引用类型值,如果引用类型支持此类转换,则使用该转换;否则,转换出错。

6.5 转换为 float 和 double

将任何值转换为 float 或 double 类型的规则如下所示:

  • 布尔值 False 转换为零;布尔值 True 转换为 1。
  • char 值得到精确表示。
  • 如果可能,数值类型会得到精确表示;但是,对于 int、long 和 decimal 转换为 float,以及 long 和 decimal 转换为 double,整数值的一些最低有效位可能会丢失。
  • null 类型的值转换为零。
  • 表示数字的字符串,将按照 §6.16中所述进行转换;否则,转换将被视为错误。
  • 对于其他引用类型值,如果引用类型支持此类转换,则使用该转换;否则,转换出错。

6.6 转换为十进制

将任何值转换为小数类型的规则如下所示:

  • 布尔值 False 转换为零;布尔值 True 转换为 1。
  • 字符类型值被准确表示。
  • 数字类型值完全表示;但是,如果该值太大或太小,无法适应目标类型,则转换将出错。
  • null 类型的值转换为零。
  • 一个代表数字的字符串会按照 §6.16中的描述进行转换,否则会发生转换错误。
  • 对于其他引用类型值,如果引用类型支持此类转换,则使用该转换;否则,转换出错。
  • 成功转换的结果标量使得小数部分没有尾随零。

6.7 转换为对象

除 null 类型(4.1.2)以外的任何类型的值都可以转换为类型对象。 该值保留其类型和表示形式。

6.8 转换为字符串

将任何值转换为类型字符串的规则如下所示:

  • 布尔值 $false 转换为“False”;布尔值 $true 转换为“True”。
  • 字符类型值转换为包含该字符的 1 个字符字符串。
  • 数值类型值转换为具有相应数值文本形式的字符串。 但是,结果中没有前导或尾随空格,没有前导加号,整数使用基数 10,并且没有类型后缀。 对于十进制转换,将保留标量。 对于 -∞、+∞ 和 NaN 的值,生成的字符串分别为“-Infinity”、“Infinity”和“NaN”。
  • null 类型的值将转换为空字符串。
  • 对于一维数组,结果是一个字符串,其中包含该数组中每个元素的值,从头到尾转换为字符串,元素由当前输出字段分隔符分隔(§2.3.2.2)。 对于包含数组自身的数组,仅转换最外层元素。 用于表示数组元素值的字符串是定义的实现。 对于多维数组,它将被平展(§9.12),然后被视为一维数组。
  • null 类型的值将转换为空字符串。
  • 脚本块类型的值会被转换为一个字符串,其中包含该块的文本,但不包括分隔符 { 和 } 字符。
  • 对于枚举类型值,结果是一个字符串,其中包含用逗号分隔的值中编码的每个枚举常量的名称。
  • 对于其他引用类型值,如果引用类型支持此类转换,则使用该转换;否则,转换出错。

用于表示数组的元素的值的字符串具有 System.type[]System.type[,]等形式。 对于其他引用类型,将调用方法 ToString。 对于其他可枚举类型,源值将被视为一个 1 维数组。

6.9 转换为数组

将任何值转换为数组类型的规则如下所示:

  • 目标类型可能不是多维数组。
  • null 类型的值保持不变。
  • 对于除 $null 和哈希表类型的值以外的标量值,将创建一个新的 1 元素数组,其值是该标量转换为目标元素类型后的结果。
  • 对于一维数组数值,将创建一个目标类型的新数组,每个元素都通过转换从源数组复制到目标数组中对应的位置。
  • 对于多维数组值,该数组首先平展(§9.12),然后被视为一维数组值。
  • 字符串值转换为字符数组,其长度相同,字符串中的连续字符占用数组中的相应位置。

对于其他可枚举类型,将创建一个新的 1 元素数组,如果存在此类转换,则创建一个新的 1 元素数组,其值是目标元素类型转换后对应的元素。 否则,转换出错。

6.10 转换为 xml

对象转换为类型字符串,然后转换为 xml类型的 XML Document 对象。

6.11 转换为正则表达式

指定字符串类型的值的表达式可以转换为类型 regex

6.12 转换为 scriptBlock

将任何值转换为类型 scriptblock 的规则如下所示:

  • 字符串值被视为命令的名称,后面可选择性地跟随对该命令的调用参数。

6.13 转换为枚举类型

将任何值转换为枚举类型的规则如下所示:

  • 一个字符串类型的值,其中包含枚举类型的某个命名值(区分大小写),将被转换为该命名值。
  • 一个字符串类型的值包含一个枚举类型的命名值列表,列表内的值用逗号分隔(需考虑大小写),将被转换为所有这些命名值的按位 OR 结果。

6.14 转换为其他引用类型

将任何值转换为数组类型或字符串以外的引用类型的规则如下所示:

  • null 类型的值按原样保留。
  • 否则,行为是由实现定义的。

在这里涉及多个机制:包括在值为哈希表时,可能使用单参数构造函数或默认构造函数,隐式和显式转换运算符,以及目标类型的 Parse 方法;Convert.ConvertTo 的使用;以及 ETS 转换机制。

6.15 常规算术转换

如果两个操作数都未指定具有数值类型的值,则

  • 如果左侧操作数指定布尔类型的值,则转换出错。
  • 否则,指定值 $null 的所有操作数将转换为 int 类型的零,然后继续执行下列数值转换。
  • 否则,如果左侧操作数指定类型字符的值,而右操作数指定布尔类型的值,则转换将出错。
  • 否则,如果左侧操作数指定字符串类型的值,但不表示数字(§6.16),则转换出错。
  • 否则,如果右操作数指定字符串类型的值,但不表示数字(§6.16),则转换出错。
  • 否则,指定字符串类型值的所有操作数将转换为数字(§6.16),该过程将继续执行下面列出的数值转换。
  • 否则,转换出错。

数值转换:

  • 如果一个操作数指定小数类型的值,则其他操作数指定的值将在必要时转换为该类型。 结果的类型为十进制。
  • 否则,如果一个操作数指定 double 类型的值,则其他操作数指定的值将在必要时转换为该类型。 结果为 double 类型。
  • 否则,如果一个操作数指定了 float 类型的值,则两个操作数指定的值将被转换为 double 类型(如有必要)。 结果为 double 类型。
  • 否则,如果一个操作数指定了长类型的值,则其他操作数值指定的值将在必要时转换为该类型。 结果是序列中第一个可以表示其值类型,包括 long 和 double。
  • 否则,两个操作数指定的值将被转换为整数类型(如果需要)。 结果是序列中第一个可以无损表示其值的类型,包括 int、long、double。

6.16 从字符串转换为数字类型

根据字符串的内容,可以显式或隐式转换为数值。 具体说来

  • 空字符串转换为值零。
  • 将忽略前导空格和尾随空格;但是,字符串不能仅包含空格。
  • 仅包含空格和/或行终止符的字符串将转换为值零。
  • 允许使用一个前导 + 或 - 符号。
  • 整数可能有十六进制前缀(0x 或 0X)。
  • 允许可选带符号的指数。
  • 不允许使用类型后缀和乘数。
  • 区分大小写的字符串“-Infinity”、“Infinity”和“NaN”分别被识别为值 -∞、+∞ 和 NaN。

6.17 参数绑定期间的转换

有关参数绑定的信息,请参阅 §8.14

当表达式的值绑定到参数时,需要考虑额外的转换注意事项,如下所示:

  • 如果参数类型为 switch(§4.2.5§8.10.5),并且参数没有参数,则调用命令中的参数值设置为 $true。 如果参数类型不是 switch,而参数缺少对应的值,则属于错误。
  • 如果参数类型为 switch,参数值 $null,则参数值设置为 $false
  • 如果参数类型为对象或与参数的类型相同,则不进行转换即可传递参数的值。
  • 如果参数类型不是对象或 scriptblock,则会计算具有类型 scriptblock 的参数,并将其结果作为参数的值传递。 (这称为 延迟脚本块绑定。)如果参数类型为对象或 scriptblock,则按原样传递具有类型 scriptblock 的参数。
  • 如果参数类型是 T2 类型的集合,并且该参数是 T1 类型的标量,则标量将转换为包含一个元素的 T2 类型的集合。 如有必要,使用本部分的转换规则将标量值转换为类型 T2。
  • 如果参数类型是对象以外的标量类型,并且参数是集合,则参数出错。
  • 如果预期的参数类型是 T2 类型的集合,并且该参数是 T1 类型的集合,则参数将转换为类型 T2 的集合,其长度与参数集合相同。 如有必要,参数集合元素值将使用本节的转换规则转换为类型 T2。
  • 如果上述步骤和本章前面指定的转换是不够的,则应用 §6.18 中的规则。 如果失败,参数绑定将失败。

6.18 .NET 转换

对于隐式转换,首先尝试 PowerShell 的内置转换。 如果它们无法解析转换,则尝试从上到下的顺序尝试下面的 .NET 自定义转换器。 如果找到转换却引发异常,则转换失败。

  • PSTypeConverter:可通过两种方式将 PSTypeConverter 类的实现与其目标类相关联:通过类型配置文件(types.ps1xml)或将 System.ComponentModel.TypeConverterAttribute 属性应用于目标类。 有关详细信息,请参阅 PowerShell SDK 文档。

  • TypeConverter:此 CLR 类型提供将值类型转换为其他类型的统一方法,以及访问标准值和子属性。 最常见的转换器类型是与文本表示形式相互转换的转换器。 类的类型转换器绑定到具有 System.ComponentModel.TypeConverterAttribute 的类。 除非重写此属性,否则继承自此类的所有类都使用与基类相同的类型转换器。 有关详细信息,请参阅 PowerShell SDK 和 Microsoft .NET Framework 文档。

  • 分析方法:如果源类型为字符串,并且目标类型具有名为 Parse的方法,则调用该方法来执行转换。

  • 构造函数:如果目标类型有一个构造函数,该构造函数接受一个参数,且该参数的类型为源类型,则调用此构造函数来执行转换。

  • 隐式转换运算符:如果源类型具有转换为目标类型的隐式强制转换运算符,则调用该运算符来执行转换。

  • 显式强制转换运算符:如果源类型具有转换为目标类型的显式强制转换运算符,则调用该运算符来执行转换。 如果目标类型具有可以从源类型转换的显式强制转换运算符,则会调用该运算符来执行转换。

  • IConvertable:调用 System.Convert.ChangeType 来执行转换。

6.19 转换为 ordered

将任何值转换为按顺序排序的伪类型的规则如下所示:

  • 如果值为哈希文本(§2.3.5.6),则结果是一个具有实现定义的类型的对象,其行为类似于哈希表,键的顺序与哈希文本中指定的顺序匹配。
  • 否则,行为将由实现定义。

哈希文本(§2.3.5.6)只能转换为 ordered。 最后将得到 System.Collections.Specialized.OrderedDictionary 的实例。

6.20 转换为 pscustomobject

将任何值转换为伪类型 pscustomobject 的规则如下所示:

  • 类型哈希表的值将转换为 PowerShell 对象。 哈希表中的每个键都会被转化为一个具有相应值的 NoteProperty。
  • 否则,行为将由实现定义。

始终允许转换,但不更改值的类型。