使用New-Variable函数创建变量时如何显式声明变量的类型?

问题描述 投票:0回答:5

如何将

myChar
中的
New-Variable -Name myChar -Value "=" -Option ReadOnly
转换为
[char]
,或者(更一般地)如何指定使用
New-Variable
创建的变量的类型?

谢谢

编辑(归功于@veefu):

[char]$sampleVariable="A"
$sampleAttributes=(Get-Variable -Name sampleVariable).Attributes[0]
New-Variable -Name myVariable
(Get-Variable -Name myVariable).Attributes.Add($sampleAttributes)
$myVariable="ab" # GENERATES CONVERSION ERROR (WHICH HELPS A LOT)
$myVariable="a"  # DOES NOT GENERATE CONVERSION ERROR (EVERYTHING'S FINE)

编辑(归功于@postanote):

[char]$anyCharacter="A"
# FOLLOWING LINE GENERATES CONVERSION ERROR (GOOD THING)
Set-Variable -Name anyCharacter -Value "ab" -Option ReadOnly
# FOLLOWING LINE DOES NOT GENERATE CONVERSION ERROR (GREAT)
Set-Variable -Name anyCharacter -Value "a" -Option ReadOnly
powershell
5个回答
5
投票

现在在 PowerShell 中几乎不可能做到这一点,因此我提出了一个问题 您应该能够使用 New-Variable 在变量上设置类型转换属性来解决此问题。


4
投票

带类型说明符和不带类型说明符的变量之间的区别

[int32]
在于变量属性:

[int32] $var1 = 32
$var2 = 'a'

Get-Variable -Name 'var1' | fl *
Get-Variable -Name 'var2' | fl *

产量:

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

Name        : var2
Description :
Value       : a
Visibility  : Public
Module      :
ModuleName  :
Options     : None
Attributes  : {}

New-Variable
不支持设置这些属性,因此不可能使用
[int32] $myVarname
 来实现与 
New-Variable

等效的功能

可以使用 .net

[psvariable]::new()
构造函数来创建具有这些属性的变量。我无法弄清楚如何从头开始构造属性以使其相当于
[int32]
,但能够在构造过程中成功地从另一个变量复制属性:

[int32] $int32ConstrainedVar1 = 32
$var1Attributes = (Get-Variable -Name 'int32ConstrainedVar1').Attributes
$newConstrainedVar = [psvariable]::new('int32ConstrainedVar2', 33, 'None', $var1Attributes)

在此之后,尝试分配无法转换为

[int32]
的内容会失败,正如预期的那样:

$newConstrainedVar.Value = 'asdf'

产量:

Exception setting "Value": "Cannot convert value "asdf" to type "System.Int32". Error: "Input string was not in a correct format.""
At line:1 char:1
+ $newConstrainedVar.Value = 'asdf'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting

抱歉,细节很粗略;这对我来说是新的 powershell 内部结构级别。

我对您的用例感兴趣;我可以想象您想要使用 powershell 在如此低的级别上工作的唯一原因是您正在编写一个从另一种语言翻译成 powershell 的运行时。


2
投票

没有单独使用 cmdlet 来按照其规范执行此操作的本机方法:

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-variable?view=powershell-6

[-Name] <String>
[[-Value] <Object>]
[-Description <String>]
[-Option <ScopedItemOptions>]
[-Visibility <SessionStateEntryVisibility>]
[-Force]
[-PassThru]
[-Scope <String>]
[-WhatIf]
[-Confirm]
[<CommonParameters>]

稍微考虑一下之后,可以在创建或内联之后应用数据类型,这样...... (相对于您的用例,可能是您的一种方式,但同样......)

[char](New-Variable -Name myChar -Value "=")
$myChar
=
$myChar.GetType()
IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     String    System.Object   

Remove-Variable -Name myChar

[int](New-Variable -Name myChar -Value 1)
0
$myChar
1
$myChar.GetType()
IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     Int32     System.ValueType

Remove-Variable -Name myChar

[decimal](New-Variable -Name myChar -Value 10.00)
0
$myChar
10.00
$myChar.GetType()
IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     Double    System.ValueType

Remove-Variable -Name myChar

变量类型

通常,当您创建变量时,您会通过使用的值隐式设置类型。有时您可能想显式设置变量类型。

如果你没有给变量指定类型,你可以这样做:

PS> $x = 35
PS> $x
35
PS> $x = 'now a string'
PS> $x
now a string

如果你给变量一个明确的类型

PS> [int]$x = 35
PS> $x
35
PS> $x = 'now a string'
Cannot convert value "now a string" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:1
+ $x = 'now a string'
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException

变量需要一个整数或可以转换为整数的东西

PS> $x = '123'
PS> $x
123

使用 New-Variable 时无法提供类型,因此如果您需要只读或常量变量,请按如上所示创建它,然后使用 Set-Variable 使其只读或常量。

https://blogs.msmvps.com/richardsiddaway/2018/08/18/variable-type

所以,这还是回到我之前的说法...

可以在创建后应用数据类型……

我之前的帖子中没有想到设置变量。


1
投票

所以有可能,我找到了方法。

以标准方式制作字符串:

[string]$var1 = 1
$var1.GetType().name

用设置变量创建一个字符串:

Set-Variable -Name var2 -Value (New-Object -TypeName System.String -ArgumentList "1")
$var2.GetType().name

它也适用于其他对象:

Set-Variable -Name var3 -Value (New-Object 'System.Collections.Generic.List[System.Object]')

0
投票

新变量 -名称 'test' -值 $([int]10) -选项只读

© www.soinside.com 2019 - 2024. All rights reserved.