Czy program PowerShell obsługuje stałe?

118

Chciałbym zadeklarować pewne stałe całkowite w PowerShell.

Czy jest na to dobry sposób?

Tom Hazel
źródło

Odpowiedzi:

121

Posługiwać się

Set-Variable test -option Constant -value 100

lub

Set-Variable test -option ReadOnly -value 100

Różnica między „Constant” i „ReadOnly” polega na tym, że zmienną tylko do odczytu można usunąć (a następnie ponownie utworzyć) za pomocą

Remove-Variable test -Force

podczas gdy stałej zmiennej nie można usunąć (nawet z -Force).

Zobacz ten artykuł TechNet, aby uzyskać więcej informacji.

Motti Strom
źródło
4
Hmm, ale jak wymusić typ danych podczas używania Set-Variable? Kiedy mamy do czynienia ze zmiennymi, można użyć, [string]$name = valueale wydaje się, że nie jest to możliwe w przypadku stałych?
masi
8
@masi po prostu wymuś wartośćSet-Variable test -option Constant -value [string]100
Monso
7
@Monso Podczas określania typu, na przykład, potrzebujesz nawiasów wokół wartości ([string]100). Zobacz odpowiedzi poniżej.
Polymorphix
15

Oto rozwiązanie umożliwiające zdefiniowanie stałej w następujący sposób:

const myConst = 42

Rozwiązanie pobrane z 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
obrabować
źródło
1
Niestety to nie działa, gdy Set-Constantjest zawarty w module. Utworzy stałą w zakresie modułu, w którym Set-Constantjest zawarta. Aby obejść ten problem, można przekazać parametr -Surround Global, ale nie zawsze jest to pożądane. Chciałbym utworzyć stałą w innym module lub lokalnie w funkcji.
zett42
11

Użyj -option Constantz Set-Variablecmdletem:

Set-Variable myvar -option Constant -value 100

Teraz $myvarma stałą wartość 100 i nie można jej modyfikować.

Paolo Tedesco
źródło
1
Wow, to niezgrabne. Aby to zrobić, musisz użyć funkcji Set-Variable, co?
Tom Hazel,
Tak, nie da się tego zrobić niezręcznie :)
Paolo Tedesco
1
możesz także modyfikować i istniejącą zmienną za pomocą set-variable (z aliasem do sv) lub używając get-variable (gv) i majstrując przy jej właściwościach Options.
x0n
Hmm, ale jak wymusić typ danych podczas używania Set-Variable? Kiedy mamy do czynienia ze zmiennymi, można użyć, [string]$name = valueale wydaje się, że nie jest to możliwe w przypadku stałych?
masi
@masi - zobacz odpowiedź Mike'a Sheparda w innym miejscu na tej stronie. Skopiuj i wklej stamtąd, to:set-variable -name test -value ([int64]100) -option Constant
Chris J
11

Aby użyć określonego typu wartości, na przykład Int64, możesz jawnie rzutować wartość używaną w ustawionej-zmiennej.

Na przykład:

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

Sprawdzić,

$test | gm

Zobaczysz, że jest to Int64 (zamiast Int32, co byłoby normalne dla wartości 100).

Mike Shepard
źródło
5

Bardzo podoba mi się cukier składniowy, który zapewnia odpowiedź Roba:

const myConst = 42

Niestety jego rozwiązanie nie działa zgodnie z oczekiwaniami, gdy definiujesz Set-Constantfunkcję w module . W przypadku wywołania spoza modułu, utworzy stałą w zakresie modułu, gdzie Set-Constantjest zdefiniowana, zamiast zakresu wywołującego . To sprawia, że ​​stała jest niewidoczna dla dzwoniącego.

Następująca zmodyfikowana funkcja rozwiązuje ten problem. Rozwiązanie opiera się na tej odpowiedzi na pytanie „Czy istnieje sposób, aby moduł PowerShell znalazł się w zasięgu osoby dzwoniącej?” .

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

Uwagi:

  • Funkcja działa tylko wtedy, gdy jest wywoływana spoza modułu, w którym została zdefiniowana. To jest zamierzony przypadek użycia, ale chciałbym dodać sprawdzenie, czy jest wywoływany z tego samego modułu (w takim przypadku Set-Variable -scope 1powinien działać), gdy dowiem się, jak to zrobić.
  • Zmieniłem nazwę parametru -Meanna -Value, aby zachować spójność z Set-Variable.
  • Funkcja może zostać rozszerzona na ewentualnie ustawienia Private, ReadOnlyi AllScopeniepokój. Po prostu dodaj żądane wartości do trzeciego argumentu PSVariablekonstruktora , który jest wywoływany w powyższym skrypcie through New-Object.
zett42
źródło
-4

Program PowerShell w wersji 5.0 powinien umożliwiać

[statyczny] [int] $ zmienna = 42

[statyczny] [DateTime] $ thisday

i tym podobne.

MarkH
źródło
2
nie działa na PS 5.1. Nie można znaleźć typu [statyczny].
ThomasMX
5
Nie wspominając o tym, że statyczność to nie to samo, co stała
Kolob Canyon