¿PowerShell admite constantes?

118

Me gustaría declarar algunas constantes enteras en PowerShell.

¿Hay alguna buena forma de hacerlo?

Tom Hazel
fuente

Respuestas:

121

Utilizar

Set-Variable test -option Constant -value 100

o

Set-Variable test -option ReadOnly -value 100

La diferencia entre "Constante" y "Solo lectura" es que una variable de solo lectura se puede eliminar (y luego volver a crear) mediante

Remove-Variable test -Force

mientras que una variable constante no se puede eliminar (incluso con -Force).

Consulte este artículo de TechNet para obtener más detalles.

Motti Strom
fuente
4
Hmm, pero ¿cómo fuerza el tipo de datos cuando lo usa Set-Variable? Cuando se trata de variables, se puede usar, [string]$name = valuepero eso parece no ser posible para las constantes.
masi
8
@masi solo fuerza el valorSet-Variable test -option Constant -value [string]100
Monso
7
@Monso Necesita paréntesis alrededor del valor al especificar el tipo como ([string]100). Vea las respuestas a continuación.
Polymorphix
15

Aquí hay una solución para definir una constante como esta:

const myConst = 42

Solución tomada de http://poshcode.org/4063

    function Set-Constant {
  <#
    .SYNOPSIS
        Creates constants.
    .DESCRIPTION
        This function can help you to create constants so easy as it possible.
        It works as keyword 'const' as such as in C#.
    .EXAMPLE
        PS C:\> Set-Constant a = 10
        PS C:\> $a += 13

        There is a integer constant declaration, so the second line return
        error.
    .EXAMPLE
        PS C:\> const str = "this is a constant string"

        You also can use word 'const' for constant declaration. There is a
        string constant named '$str' in this example.
    .LINK
        Set-Variable
        About_Functions_Advanced_Parameters
  #>
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$true, Position=0)]
    [string][ValidateNotNullOrEmpty()]$Name,

    [Parameter(Mandatory=$true, Position=1)]
    [char][ValidateSet("=")]$Link,

    [Parameter(Mandatory=$true, Position=2)]
    [object][ValidateNotNullOrEmpty()]$Mean,

    [Parameter(Mandatory=$false)]
    [string]$Surround = "script"
  )

  Set-Variable -n $name -val $mean -opt Constant -s $surround
}

Set-Alias const Set-Constant
robar
fuente
1
Desafortunadamente, esto no funciona cuando Set-Constantestá contenido en un módulo. Creará una constante en el alcance del módulo, donde Set-Constantestá contenido. Como solución alternativa, se podría pasar un parámetro -Surround Global, pero eso no siempre se desea. Me gustaría crear una constante en otro módulo o localmente en una función.
zett42
11

Usar -option Constantcon el Set-Variablecmdlet:

Set-Variable myvar -option Constant -value 100

Ahora $myvartiene un valor constante de 100 y no se puede modificar.

Paolo Tedesco
fuente
1
Vaya, eso es torpe. Tienes que usar Set-Variable para hacerlo, ¿eh?
Tom Hazel
Sí, no hay forma poco torpe de hacerlo :)
Paolo Tedesco
1
también puede modificar una variable existente con set-variable (alias a sv) o usando get-variable (gv) y jugando con su propiedad Options.
x0n
Hmm, pero ¿cómo fuerza el tipo de datos cuando lo usa Set-Variable? Cuando se trata de variables, se puede usar, [string]$name = valuepero eso parece no ser posible para las constantes.
masi
@masi: consulte la respuesta de Mike Shepard en otra parte de esta página. Copiar y pegar desde allí, es:set-variable -name test -value ([int64]100) -option Constant
Chris J
11

Para usar un tipo de valor específico, digamos Int64, puede convertir explícitamente el valor usado en set-variable.

Por ejemplo:

set-variable -name test -value ([int64]100) -option Constant

Verificar,

$test | gm

Y verá que es un Int64 (en lugar de Int32, que sería normal para el valor 100).

Mike Shepard
fuente
5

Realmente me gusta el azúcar sintáctico que proporciona la respuesta de Rob:

const myConst = 42

Desafortunadamente, su solución no funciona como se esperaba cuando define la Set-Constantfunción en un módulo . Cuando se llama desde fuera del módulo, creará una constante en el alcance del módulo, donde Set-Constantse define, en lugar del alcance del llamador . Esto hace que la constante sea invisible para la persona que llama.

La siguiente función modificada soluciona este problema. La solución se basa en esta respuesta a la pregunta "¿Hay alguna forma de que un módulo de PowerShell llegue al alcance de su llamador?" .

function Set-Constant {
    <#
    .SYNOPSIS
        Creates constants.
    .DESCRIPTION
        This function can help you to create constants so easy as it possible.
        It works as keyword 'const' as such as in C#.
    .EXAMPLE
        PS C:\> Set-Constant a = 10
        PS C:\> $a += 13

        There is a integer constant declaration, so the second line return
        error.
    .EXAMPLE
        PS C:\> const str = "this is a constant string"

        You also can use word 'const' for constant declaration. There is a
        string constant named '$str' in this example.
    .LINK
        Set-Variable
        About_Functions_Advanced_Parameters
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=0)] [string] [ValidateNotNullOrEmpty()] $Name,
        [Parameter(Mandatory=$true, Position=1)] [char] [ValidateSet("=")] $Link,
        [Parameter(Mandatory=$true, Position=2)] [object] [ValidateNotNullOrEmpty()] $Value
    )

    $var = New-Object System.Management.Automation.PSVariable -ArgumentList @(
        $Name, $Value, [System.Management.Automation.ScopedItemOptions]::Constant
    )

    $PSCmdlet.SessionState.PSVariable.Set( $var )
}

Set-Alias const Set-Constant

Notas:

  • La función solo funciona cuando se llama desde fuera del módulo, donde está definida. Este es el caso de uso previsto, pero me gustaría agregar una verificación, si se llama desde el mismo módulo (en cuyo caso Set-Variable -scope 1debería funcionar), cuando descubra cómo hacerlo.
  • Cambié el nombre del parámetro -Meana -Value, por coherencia con Set-Variable.
  • La función podría ampliarse para configurar opcionalmente los indicadores Private, ReadOnlyy AllScope. Simplemente agregue los valores deseados al tercer argumento del PSVariableconstructor , al que se llama en el script anterior New-Object.
zett42
fuente
-4

PowerShell v5.0 debería permitir

[estática] [int] $ variable = 42

[estática] [DateTime] $ este día

y similares.

MarkH
fuente
2
no funciona en ps 5.1. No se pudo encontrar el tipo [estático].
ThomasMX
5
Sin mencionar que la estática no es lo mismo que una constante
Kolob Canyon