about_Classes_Methods

Krátký popis

Popisuje, jak definovat metody pro třídy PowerShellu.

Dlouhý popis

Metody definují akce, které mohou třídy provádět. Metody mohou přijímat parametry, které určují vstupní data. Metody vždy definují výstupní typ. Pokud metoda nevrací žádný výstup, musí mít výstupní typ Void . Pokud metoda explicitně nedefinuje výstupní typ, je výstupní typ metody Void.

V metodách třídy se do kanálu neposílají žádné objekty s výjimkou objektů zadaných return v příkazu. Z kódu neexistuje žádný náhodný výstup kanálu.

Poznámka:

To se v podstatě liší od toho, jak funkce PowerShellu zpracovávají výstup, kde všechno směřuje do kanálu.

Neprocházející chyby zapsané do datového proudu chyb uvnitř metody třídy se nepřecházejí. K zobrazení ukončovací chyby je nutné použít throw . Write-* Pomocí rutin můžete dál zapisovat do výstupních datových proudů PowerShellu z metody třídy. Rutiny respektují proměnné předvoleb v oboru volání. Měli byste se však vyhnout použití Write-* rutin, aby metoda výstupem pouze objekty pomocí příkazu return .

Metody třídy mohou odkazovat na aktuální instanci objektu třídy pomocí $this automatické proměnné pro přístup k vlastnostem a dalším metodám definovaným v aktuální třídě. Automatická $this proměnná není dostupná ve statických metodách.

Metody tříd mohou mít libovolný počet atributů, včetně skrytých a statických atributů.

Syntaxe

Metody tříd používají následující syntaxe:

Jednořádková syntaxe

[[<attribute>]...] [hidden] [static] [<output-type>] <method-name> ([<method-parameters>]) { <body> }

Víceřádkové syntaxe

[[<attribute>]...]
[hidden]
[static]
[<output-type>] <method-name> ([<method-parameters>]) {
  <body>
}

Příklady

Příklad 1 – minimální definice metody

Metoda GetVolume()ExampleCube1 třídy vrátí svazek datové krychle. Definuje výstupní typ jako číslo s plovoucí desetinnou čárkou a vrátí výsledek vynásobení vlastností Height, Length a Width instance.

class ExampleCube1 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() { return $this.Height * $this.Length * $this.Width }
}

$box = [ExampleCube1]@{
    Height = 2
    Length = 2
    Width  = 3
}

$box.GetVolume()
12

Příklad 2 – metoda s parametry

Metoda GeWeight() vezme plovoucí číselný vstup pro hustotu datové krychle a vrátí váhu datové krychle vypočítané jako objem vynásobený hustotou.

class ExampleCube2 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() { return $this.Height * $this.Length * $this.Width }
    [float] GetWeight([float]$Density) {
        return $this.GetVolume() * $Density
    }
}

$cube = [ExampleCube2]@{
    Height = 2
    Length = 2
    Width  = 3
}

$cube.GetWeight(2.5)
30

Příklad 3 – metoda bez výstupu

Tento příklad definuje metodu Validate() s výstupním typem jako System.Void. Tato metoda nevrací žádný výstup. Místo toho, pokud se ověření nezdaří, vyvolá chybu. Metoda GetVolume() volá Validate() před výpočtem objemu datové krychle. Pokud ověření selže, metoda se ukončí před výpočtem.

class ExampleCube3 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() {
        $this.Validate()

        return $this.Height * $this.Length * $this.Width
    }

    [void] Validate() {
        $InvalidProperties = @()
        foreach ($Property in @('Height', 'Length', 'Width')) {
            if ($this.$Property -le 0) {
                $InvalidProperties += $Property
            }
        }

        if ($InvalidProperties.Count -gt 0) {
            $Message = @(
                'Invalid cube properties'
                "('$($InvalidProperties -join "', '")'):"
                "Cube dimensions must all be positive numbers."
            ) -join ' '
            throw $Message
        }
    }
}

$Cube = [ExampleCube3]@{ Length = 1 ; Width = -1 }
$Cube

$Cube.GetVolume()
Height Length Width
------ ------ -----
  0.00   1.00 -1.00

Exception:
Line |
  20 |              throw $Message
     |              ~~~~~~~~~~~~~~
     | Invalid cube properties ('Height', 'Width'): Cube dimensions must
     | all be positive numbers.

Metoda vyvolá výjimku, protože vlastnosti Height a Width jsou neplatné, což brání třídě v výpočtu aktuálního svazku.

Příklad 4 – Statická metoda s přetíženími

Třída ExampleCube4 definuje statickou metodu GetVolume() se dvěma přetíženími. První přetížení má parametry pro dimenze datové krychle a příznak označující, zda metoda má ověřit vstup.

Druhé přetížení zahrnuje pouze číselné vstupy. Volá první přetížení s $Static jako $true. Druhé přetížení poskytuje uživatelům způsob, jak volat metodu, aniž by vždy museli definovat, zda má být vstup přísně ověřen.

Třída také definuje GetVolume() jako instanci (nonstatic). Tato metoda volá druhé statické přetížení a zajišťuje, aby metoda instance GetVolume() před vrácením výstupní hodnoty vždy ověřila dimenze datové krychle.

class ExampleCube4 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    static [float] GetVolume(
        [float]$Height,
        [float]$Length,
        [float]$Width,
        [boolean]$Strict
    ) {
        $Signature = "[ExampleCube4]::GetVolume({0}, {1}, {2}, {3})"
        $Signature = $Signature -f $Height, $Length, $Width, $Strict
        Write-Verbose "Called $Signature"

        if ($Strict) {
            [ValidateScript({$_ -gt 0 })]$Height = $Height
            [ValidateScript({$_ -gt 0 })]$Length = $Length
            [ValidateScript({$_ -gt 0 })]$Width  = $Width
        }

        return $Height * $Length * $Width
    }

    static [float] GetVolume([float]$Height, [float]$Length, [float]$Width) {
        $Signature = "[ExampleCube4]::GetVolume($Height, $Length, $Width)"
        Write-Verbose "Called $Signature"

        return [ExampleCube4]::GetVolume($Height, $Length, $Width, $true)
    }

    [float] GetVolume() {
        Write-Verbose "Called `$this.GetVolume()"
        return [ExampleCube4]::GetVolume(
            $this.Height,
            $this.Length,
            $this.Width
        )
    }
}

$VerbosePreference = 'Continue'
$Cube = [ExampleCube4]@{ Height = 2 ; Length = 2 }
$Cube.GetVolume()
VERBOSE: Called $this.GetVolume()
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0)
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0, True)

MetadataError:
Line |
  19 |              [ValidateScript({$_ -gt 0 })]$Width  = $Width
     |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The variable cannot be validated because the value 0 is not a valid
     | value for the Width variable.

Podrobné zprávy v definicích metody ukazují, jak počáteční volání $this.GetVolume() volání statické metody.

Volání statické metody přímo s strict parametr jako $false vrací 0 pro svazek.

[ExampleCube4]::GetVolume($Cube.Height, $Cube.Length, $Cube.Width, $false)
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0, False)
0

Podpisy a přetížení metody

Každá metoda třídy má jedinečný podpis, který definuje, jak metodu volat. Výstupní typ, název a parametry metody definují podpis metody.

Když třída definuje více než jednu metodu se stejným názvem, definice této metody jsou přetížení. Přetížení metody musí mít různé parametry. Metoda nemůže definovat dvě implementace se stejnými parametry, i když jsou typy výstupu odlišné.

Následující třída definuje dvě metody Shuffle() a Deal(). Metoda Deal() definuje dvě přetížení, jedno bez parametrů a druhý s parametrem Count .

class CardDeck {
    [string[]]$Cards  = @()
    hidden [string[]]$Dealt  = @()
    hidden [string[]]$Suits  = @('Clubs', 'Diamonds', 'Hearts', 'Spades')
    hidden [string[]]$Values = 2..10 + @('Jack', 'Queen', 'King', 'Ace')

    CardDeck() {
        foreach($Suit in $this.Suits) {
            foreach($Value in $this.Values) {
                $this.Cards += "$Value of $Suit"
            }
        }
        $this.Shuffle()
    }

    [void] Shuffle() {
        $this.Cards = $this.Cards + $this.Dealt | Where-Object -FilterScript {
             -not [string]::IsNullOrEmpty($_)
        } | Get-Random -Count $this.Cards.Count
    }

    [string] Deal() {
        if ($this.Cards.Count -eq 0) { throw "There are no cards left." }

        $Card        = $this.Cards[0]
        $this.Cards  = $this.Cards[1..$this.Cards.Count]
        $this.Dealt += $Card

        return $Card
    }

    [string[]] Deal([int]$Count) {
        if ($Count -gt $this.Cards.Count) {
            throw "There are only $($this.Cards.Count) cards left."
        } elseif ($Count -lt 1) {
            throw "You must deal at least 1 card."
        }

        return (1..$Count | ForEach-Object { $this.Deal() })
    }
}

Výstup metody

Ve výchozím nastavení metody nemají žádný výstup. Pokud podpis metody obsahuje explicitní výstupní typ jiný než Void, musí metoda vrátit objekt tohoto typu. Metody nevygenerují žádný výstup s výjimkou případů, kdy return klíčové slovo explicitně vrací objekt.

Parametry metody

Metody třídy mohou definovat vstupní parametry, které se mají použít v těle metody. Parametry metody jsou uzavřeny v závorkách a jsou odděleny čárkami. Prázdné závorky označují, že metoda nevyžaduje žádné parametry.

Parametry lze definovat na jednom řádku nebo více řádcích. Následující bloky zobrazují syntaxi parametrů metody.

([[<parameter-type>]]$<parameter-name>[, [[<parameter-type>]]$<parameter-name>])
(
    [[<parameter-type>]]$<parameter-name>[,
    [[<parameter-type>]]$<parameter-name>]
)

Parametry metody mohou být silného typu. Pokud parametr není zadán, metoda přijme pro tento parametr jakýkoli objekt. Pokud je parametr zadán, metoda se pokusí převést hodnotu pro tento parametr na správný typ, vyvolá výjimku, pokud vstup nelze převést.

Parametry metody nemůžou definovat výchozí hodnoty. Všechny parametry metody jsou povinné.

Parametry metody nemohou mít žádné další atributy. To brání metodám v používání parametrů s Validate* atributy. Další informace o ověřovacích atributech najdete v tématu about_Functions_Advanced_Parameters.

K přidání ověřování k parametrům metody můžete použít jeden z následujících vzorů:

  1. Znovu přiřaďte parametry ke stejným proměnným s požadovanými ověřovacími atributy. To funguje pro statické i instance metody. Příklad tohoto modelu najdete v příkladu 4.
  2. Slouží Update-TypeData k definování ScriptMethod atributu ověření na parametrech přímo. To funguje jenom pro metody instancí. Další informace naleznete v části Definování metod instance pomocí Update-TypeData .

Automatické proměnné v metodách

Ne všechny automatické proměnné jsou dostupné v metodách. Následující seznam obsahuje automatické proměnné a návrhy, zda a jak je používat v metodách třídy PowerShellu. Automatické proměnné, které nejsou zahrnuté v seznamu, nejsou dostupné pro metody tříd.

  • $_ - Přístup jako normální.
  • $args – Místo toho použijte explicitní proměnné parametrů.
  • $ConsoleFileName - Přístup jako $Script:ConsoleFileName místo toho.
  • $Error - Přístup jako normální.
  • $EnabledExperimentalFeatures - Přístup jako $Script:EnabledExperimentalFeatures místo toho.
  • $Event - Přístup jako normální.
  • $EventArgs - Přístup jako normální.
  • $EventSubscriber - Přístup jako normální.
  • $ExecutionContext - Přístup jako $Script:ExecutionContext místo toho.
  • $false - Přístup jako normální.
  • $foreach - Přístup jako normální.
  • $HOME - Přístup jako $Script:HOME místo toho.
  • $Host - Přístup jako $Script:Host místo toho.
  • $input – Místo toho použijte explicitní proměnné parametrů.
  • $IsCoreCLR - Přístup jako $Script:IsCoreCLR místo toho.
  • $IsLinux - Přístup jako $Script:IsLinux místo toho.
  • $IsMacOS - Přístup jako $Script:IsMacOS místo toho.
  • $IsWindows - Přístup jako $Script:IsWindows místo toho.
  • $LASTEXITCODE - Přístup jako normální.
  • $Matches - Přístup jako normální.
  • $MyInvocation - Přístup jako normální.
  • $NestedPromptLevel - Přístup jako normální.
  • $null - Přístup jako normální.
  • $PID - Přístup jako $Script:PID místo toho.
  • $PROFILE - Přístup jako $Script:PROFILE místo toho.
  • $PSBoundParameters – Tuto proměnnou nepoužívejte. Je určená pro rutiny a funkce. Použití ve třídě může mít neočekávané vedlejší účinky.
  • $PSCmdlet – Tuto proměnnou nepoužívejte. Je určená pro rutiny a funkce. Použití ve třídě může mít neočekávané vedlejší účinky.
  • $PSCommandPath - Přístup jako normální.
  • $PSCulture - Přístup jako $Script:PSCulture místo toho.
  • $PSEdition - Přístup jako $Script:PSEdition místo toho.
  • $PSHOME - Přístup jako $Script:PSHOME místo toho.
  • $PSItem - Přístup jako normální.
  • $PSScriptRoot - Přístup jako normální.
  • $PSSenderInfo - Přístup jako $Script:PSSenderInfo místo toho.
  • $PSUICulture - Přístup jako $Script:PSUICulture místo toho.
  • $PSVersionTable - Přístup jako $Script:PSVersionTable místo toho.
  • $PWD - Přístup jako normální.
  • $Sender - Přístup jako normální.
  • $ShellId - Přístup jako $Script:ShellId místo toho.
  • $StackTrace - Přístup jako normální.
  • $switch - Přístup jako normální.
  • $this - Přístup jako normální. V metodě $this třídy je vždy aktuální instance třídy. K vlastnostem a metodám třídy můžete přistupovat. Není k dispozici ve statických metodách.
  • $true - Přístup jako normální.

Další informace o automatických proměnných najdete v tématu about_Automatic_Variables.

Skryté metody

Metody třídy můžete skrýt deklarováním pomocí klíčového hidden slova. Skryté metody třídy jsou:

  • Součástí seznamu členů třídy vrácených rutinou Get-Member není. Pokud chcete zobrazit skryté metody, Get-Memberpoužijte parametr Force .
  • Nezobrazuje se v dokončování tabulátoru nebo IntelliSense, pokud nedojde k dokončení ve třídě, která definuje skrytou metodu.
  • Veřejné členy třídy. Mohou být volána a děděna. Skrytí metody ji neudělá jako soukromou. Skryje metodu, jak je popsáno v předchozích bodech.

Poznámka:

Když skryjete jakékoli přetížení pro metodu, tato metoda je odebrána z IntelliSense, výsledky dokončení a výchozí výstup pro Get-Member.

Další informace o klíčovém slově hidden najdete v tématu about_Hidden.

Statické metody

Metodu můžete definovat jako vlastní třídu namísto instancí třídy deklarací metody s klíčovým slovem static . Statické metody třídy:

  • Jsou vždy k dispozici nezávisle na vytváření instancí třídy.
  • Sdílí se napříč všemi instancemi třídy.
  • Jsou vždy k dispozici.
  • Nelze získat přístup k vlastnostem instance třídy. Mají přístup pouze ke statickým vlastnostem.
  • Živě pro celou relaci.

Metody odvozené třídy

Když třída je odvozena ze základní třídy, dědí metody základní třídy a jejich přetížení. Všechny přetížení metody definované na základní třídě, včetně skrytých metod, jsou k dispozici v odvozené třídě.

Odvozená třída může přepsat přetížení zděděné metody opětovným definováním v definici třídy. Chcete-li přepsat přetížení, musí být typy parametrů stejné jako pro základní třídu. Typ výstupu přetížení se může lišit.

Na rozdíl od konstruktorů metody nemůžou : base(<parameters>) syntaxi použít k vyvolání přetížení základní třídy pro metodu. Redefined přetížení odvozené třídy zcela nahrazuje přetížení definované základní třídou.

Následující příklad ukazuje chování statických metod a metod instancí na odvozených třídách.

Základní třída definuje:

  • Statické metody Now() pro vrácení aktuálního času a DaysAgo() vrácení data v minulosti.
  • Instance vlastnost TimeStamp a ToString() instance metoda, která vrací řetězcovou reprezentaci této vlastnosti. Tím se zajistí, že při použití instance v řetězci se místo názvu třídy převede na řetězec datetime.
  • Metoda SetTimeStamp() instance se dvěma přetíženími. Když je volána metoda bez parametrů, nastaví TimeStamp na aktuální čas. Když je volána metoda s DateTime, nastaví TimeStamp na tuto hodnotu.
class BaseClass {
    static [datetime] Now() {
        return Get-Date
    }
    static [datetime] DaysAgo([int]$Count) {
        return [BaseClass]::Now().AddDays(-$Count)
    }

    [datetime] $TimeStamp = [BaseClass]::Now()

    [string] ToString() {
        return $this.TimeStamp.ToString()
    }

    [void] SetTimeStamp([datetime]$TimeStamp) {
        $this.TimeStamp = $TimeStamp
    }
    [void] SetTimeStamp() {
        $this.TimeStamp = [BaseClass]::Now()
    }
}

Další blok definuje třídy odvozené z BaseClass:

  • DerivedClassA dědí z Třídy BaseClass bez jakýchkoli přepsání.
  • DerivedClassB přepíše statickou metodu DaysAgo() tak, aby místo objektu DateTime vrátila řetězcovou reprezentaci. Přepíše také metodu ToString() instance tak, aby vrátila časové razítko jako řetězec ISO8601 kalendářního data.
  • DerivedClassC přepíše přetížení bez SetTimeStamp() parametrů metody tak, aby nastavení časového razítka bez parametrů nastavil datum na 10 dní před aktuálním datem.
class DerivedClassA : BaseClass     {}
class DerivedClassB : BaseClass     {
    static [string] DaysAgo([int]$Count) {
        return [BaseClass]::DaysAgo($Count).ToString('yyyy-MM-dd')
    }
    [string] ToString() {
        return $this.TimeStamp.ToString('yyyy-MM-dd')
    }
}
class DerivedClassC : BaseClass {
    [void] SetTimeStamp() {
        $this.SetTimeStamp([BaseClass]::Now().AddDays(-10))
    }
}

Následující blok ukazuje výstup statické Now() metody pro definované třídy. Výstup je stejný pro každou třídu, protože odvozené třídy nepřepíší implementaci základní třídy metody.

"[BaseClass]::Now()     => $([BaseClass]::Now())"
"[DerivedClassA]::Now() => $([DerivedClassA]::Now())"
"[DerivedClassB]::Now() => $([DerivedClassB]::Now())"
"[DerivedClassC]::Now() => $([DerivedClassC]::Now())"
[BaseClass]::Now()     => 11/06/2023 09:41:23
[DerivedClassA]::Now() => 11/06/2023 09:41:23
[DerivedClassB]::Now() => 11/06/2023 09:41:23
[DerivedClassC]::Now() => 11/06/2023 09:41:23

Další blok volá statickou metodu DaysAgo() každé třídy. Pouze výstup pro DerivedClassB se liší, protože přerodí základní implementaci.

"[BaseClass]::DaysAgo(3)     => $([BaseClass]::DaysAgo(3))"
"[DerivedClassA]::DaysAgo(3) => $([DerivedClassA]::DaysAgo(3))"
"[DerivedClassB]::DaysAgo(3) => $([DerivedClassB]::DaysAgo(3))"
"[DerivedClassC]::DaysAgo(3) => $([DerivedClassC]::DaysAgo(3))"
[BaseClass]::DaysAgo(3)     => 11/03/2023 09:41:38
[DerivedClassA]::DaysAgo(3) => 11/03/2023 09:41:38
[DerivedClassB]::DaysAgo(3) => 2023-11-03
[DerivedClassC]::DaysAgo(3) => 11/03/2023 09:41:38

Následující blok ukazuje řetězcovou prezentaci nové instance pro každou třídu. Reprezentace pro DerivedClassB je odlišná, protože přerodí metodu ToString() instance.

"`$base = [BaseClass]::New()     => $($base = [BaseClass]::New(); $base)"
"`$a    = [DerivedClassA]::New() => $($a = [DerivedClassA]::New(); $a)"
"`$b    = [DerivedClassB]::New() => $($b = [DerivedClassB]::New(); $b)"
"`$c    = [DerivedClassC]::New() => $($c = [DerivedClassC]::New(); $c)"
$base = [BaseClass]::New()     => 11/6/2023 9:44:57 AM
$a    = [DerivedClassA]::New() => 11/6/2023 9:44:57 AM
$b    = [DerivedClassB]::New() => 2023-11-06
$c    = [DerivedClassC]::New() => 11/6/2023 9:44:57 AM

Další blok volá metodu SetTimeStamp() instance pro každou instanci a nastaví vlastnost TimeStamp na konkrétní datum. Každá instance má stejné datum, protože žádná z odvozených tříd nepřepíše parametrizované přetížení metody.

[datetime]$Stamp = '2024-10-31'
"`$base.SetTimeStamp(`$Stamp) => $($base.SetTimeStamp($Stamp) ; $base)"
"`$a.SetTimeStamp(`$Stamp)    => $($a.SetTimeStamp($Stamp); $a)"
"`$b.SetTimeStamp(`$Stamp)    => $($b.SetTimeStamp($Stamp); $b)"
"`$c.SetTimeStamp(`$Stamp)    => $($c.SetTimeStamp($Stamp); $c)"
$base.SetTimeStamp($Stamp) => 10/31/2024 12:00:00 AM
$a.SetTimeStamp($Stamp)    => 10/31/2024 12:00:00 AM
$b.SetTimeStamp($Stamp)    => 2024-10-31
$c.SetTimeStamp($Stamp)    => 10/31/2024 12:00:00 AM

Poslední bloková volání SetTimeStamp() bez jakýchkoli parametrů. Výstup ukazuje, že hodnota instance DerivedClassC je nastavena na 10 dní před ostatními.

"`$base.SetTimeStamp() => $($base.SetTimeStamp() ; $base)"
"`$a.SetTimeStamp()    => $($a.SetTimeStamp(); $a)"
"`$b.SetTimeStamp()    => $($b.SetTimeStamp(); $b)"
"`$c.SetTimeStamp()    => $($c.SetTimeStamp(); $c)"
$base.SetTimeStamp() => 11/6/2023 9:53:58 AM
$a.SetTimeStamp()    => 11/6/2023 9:53:58 AM
$b.SetTimeStamp()    => 2023-11-06
$c.SetTimeStamp()    => 10/27/2023 9:53:58 AM

Definování metod instance pomocí Update-TypeData

Kromě deklarování metod přímo v definici třídy můžete pomocí rutiny definovat metody pro instance třídy ve statickém konstruktoru Update-TypeData .

Tento fragment kódu použijte jako výchozí bod pro vzor. Podle potřeby nahraďte zástupný text v úhlových závorkách.

class <ClassName> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            MemberName = '<MethodName>'
            MemberType = 'ScriptMethod'
            Value      = {
              param(<method-parameters>)

              <method-body>
            }
        }
    )

    static <ClassName>() {
        $TypeName = [<ClassName>].Name
        foreach ($Definition in [<ClassName>]::MemberDefinitions) {
            Update-TypeData -TypeName $TypeName @Definition
        }
    }
}

Tip

Rutina Add-Member může přidat vlastnosti a metody do třídy v nestatického konstruktoru, ale rutina se spustí při každém zavolání konstruktoru. Použití Update-TypeData ve statickém konstruktoru zajišťuje, že kód pro přidání členů do třídy musí běžet pouze jednou v relaci.

Definování metod s výchozími hodnotami parametrů a ověřovacími atributy

Metody definované přímo v deklaraci třídy nemůžou definovat výchozí hodnoty ani ověřovací atributy parametrů metody. Chcete-li definovat metody třídy s výchozími hodnotami nebo ověřovacími atributy, musí být definovány jako ScriptMethod členy.

V tomto příkladu třída CardDeck definuje metodu Draw() , která používá ověřovací atribut i výchozí hodnotu parametru Count .

class CookieJar {
    [int] $Cookies = 12

    static [hashtable[]] $MemberDefinitions = @(
        @{
            MemberName = 'Eat'
            MemberType = 'ScriptMethod'
            Value      = {
                param(
                    [ValidateScript({ $_ -ge 1 -and $_ -le $this.Cookies })]
                    [int] $Count = 1
                )

                $this.Cookies -= $Count
                if ($Count -eq 1) {
                    "You ate 1 cookie. There are $($this.Cookies) left."
                } else {
                    "You ate $Count cookies. There are $($this.Cookies) left."
                }
            }
        }
    )

    static CookieJar() {
        $TypeName = [CookieJar].Name
        foreach ($Definition in [CookieJar]::MemberDefinitions) {
            Update-TypeData -TypeName $TypeName @Definition
        }
    }
}

$Jar = [CookieJar]::new()
$Jar.Eat(1)
$Jar.Eat()
$Jar.Eat(20)
$Jar.Eat(6)
You ate 1 cookie. There are 11 left.

You ate 1 cookie. There are 10 left.

MethodInvocationException:
Line |
  36 |  $Jar.Eat(20)
     |  ~~~~~~~~~~~~
     | Exception calling "Eat" with "1" argument(s): "The attribute
     | cannot be added because variable Count with value 20 would no
     | longer be valid."

You ate 6 cookies. There are 4 left.

Poznámka:

I když tento model funguje pro ověřovací atributy, všimněte si, že výjimka je zavádějící a odkazuje na nemožnost přidat atribut. Může to být lepší uživatelské prostředí pro explicitní kontrolu hodnoty parametru a vyvolání smysluplné chyby. Uživatelé tak můžou pochopit, proč se jim zobrazuje chyba a co s tím dělat.

Omezení

Metody třídy PowerShellu mají následující omezení:

  • Parametry metody nemůžou používat žádné atributy, včetně ověřovacích atributů.

    Alternativní řešení: Přeřaďte parametry v těle metody pomocí ověřovacího atributu nebo definujte metodu ve statickém konstruktoru pomocí rutiny Update-TypeData .

  • Parametry metody nemůžou definovat výchozí hodnoty. Parametry jsou vždy povinné.

    Alternativní řešení: Definujte metodu ve statickém konstruktoru pomocí rutiny Update-TypeData .

  • Metody jsou vždy veřejné, i když jsou skryté. Mohou být přepsány, když je třída zděděna.

    Řešení: Žádné.

  • Pokud je jakékoli přetížení metody skryté, je každé přetížení této metody považováno za skryté.

    Řešení: Žádné.

Viz také