about_Classes_Methods

Kort beskrivning

Beskriver hur du definierar metoder för PowerShell-klasser.

Lång beskrivning

Metoder definierar de åtgärder som en klass kan utföra. Metoder kan ta parametrar som anger indata. Metoder definierar alltid en utdatatyp. Om en metod inte returnerar några utdata måste den ha utdatatypen Void . Om en metod inte uttryckligen definierar en utdatatyp är metodens utdatatyp Void.

I klassmetoder skickas inga objekt till pipelinen förutom de som anges i -instruktionen return . Det finns inga oavsiktliga utdata till pipelinen från koden.

Kommentar

Detta skiljer sig i grunden från hur PowerShell-funktioner hanterar utdata, där allt går till pipelinen.

Icke-avslutande fel som skrivs till felströmmen inifrån en klassmetod skickas inte igenom. Du måste använda throw för att visa ett avslutande fel. Med hjälp av Write-* cmdletarna kan du fortfarande skriva till PowerShells utdataströmmar inifrån en klassmetod. Cmdletarna respekterar inställningsvariablerna i anropsomfånget. Du bör dock undvika att använda Write-* cmdletarna så att metoden endast matar ut objekt med hjälp av -instruktionen return .

Klassmetoder kan referera till den aktuella instansen av klassobjektet med hjälp av den $this automatiska variabeln för att komma åt egenskaper och andra metoder som definierats i den aktuella klassen. Den $this automatiska variabeln är inte tillgänglig i statiska metoder.

Klassmetoder kan ha valfritt antal attribut, inklusive dolda och statiska attribut.

Syntax

Klassmetoder använder följande syntaxer:

Enradssyntax

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

Syntax för flera ledningar

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

Exempel

Exempel 1 – Minimal metoddefinition

Metoden GetVolume() för klassen ExampleCube1 returnerar kubens volym. Den definierar utdatatypen som ett flytande tal och returnerar resultatet av att multiplicera egenskaperna Höjd, Längd och Bredd för instansen.

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

Exempel 2 – Metod med parametrar

Metoden GeWeight() tar en indata för flytande tal för kubens densitet och returnerar kubens vikt, beräknad som volym multiplicerad med densitet.

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

Exempel 3 – Metod utan utdata

I det Validate() här exemplet definieras metoden med utdatatypen som System.Void. Den här metoden returnerar inga utdata. Om valideringen misslyckas utlöser den i stället ett fel. Metoden GetVolume() anropar Validate() innan kubens volym beräknas. Om verifieringen misslyckas avslutas metoden innan beräkningen.

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.

Metoden genererar ett undantag eftersom egenskaperna Höjd och Bredd är ogiltiga, vilket hindrar klassen från att beräkna den aktuella volymen.

Exempel 4 – Statisk metod med överlagringar

Klassen ExampleCube4 definierar den statiska metoden GetVolume() med två överlagringar. Den första överlagringen har parametrar för kubens dimensioner och en flagga som anger om metoden ska verifiera indata.

Den andra överlagringen innehåller endast numeriska indata. Den anropar den första överlagringen med $Static som $true. Den andra överlagringen ger användarna ett sätt att anropa metoden utan att alltid behöva definiera om indata ska verifieras strikt.

Klassen definierar GetVolume() också som en instansmetod (icke-statisk). Den här metoden anropar den andra statiska överlagringen, vilket säkerställer att instansmetoden GetVolume() alltid validerar kubens dimensioner innan utdatavärdet returneras.

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.

De utförliga meddelandena i metoddefinitionerna visar hur det första anropet till $this.GetVolume() anropar den statiska metoden.

Anropa den statiska metoden direkt med parametern Strict som $false returnerar 0 för volymen.

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

Metodsignaturer och överlagringar

Varje klassmetod har en unik signatur som definierar hur metoden ska anropas. Metodens utdatatyp, namn och parametrar definierar metodsignaturen.

När en klass definierar mer än en metod med samma namn är definitionerna för metoden överbelastningar. Överlagringar för en metod måste ha olika parametrar. En metod kan inte definiera två implementeringar med samma parametrar, även om utdatatyperna är olika.

Följande klass definierar två metoder och Shuffle()Deal(). Metoden Deal() definierar två överlagringar, en utan parametrar och den andra med parametern 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() })
    }
}

Metodutdata

Som standard har metoderna inga utdata. Om en metodsignatur innehåller en annan explicit utdatatyp än Void måste metoden returnera ett objekt av den typen. Metoder genererar inga utdata förutom när nyckelordet uttryckligen return returnerar ett objekt.

Metodparametrar

Klassmetoder kan definiera indataparametrar som ska användas i metodtexten. Metodparametrar omges av parenteser och avgränsas med kommatecken. Tomma parenteser anger att metoden inte kräver några parametrar.

Parametrar kan definieras på en enskild rad eller flera rader. Följande block visar syntaxen för metodparametrar.

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

Metodparametrar kan skrivas starkt. Om en parameter inte skrivs accepterar metoden alla objekt för den parametern. Om parametern skrivs försöker metoden konvertera värdet för parametern till rätt typ, vilket utlöser ett undantag om indata inte kan konverteras.

Metodparametrar kan inte definiera standardvärden. Alla metodparametrar är obligatoriska.

Metodparametrar kan inte ha några andra attribut. Detta förhindrar metoder från att använda parametrar med attributen Validate* . Mer information om valideringsattributen finns i about_Functions_Advanced_Parameters.

Du kan använda något av följande mönster för att lägga till validering i metodparametrar:

  1. Tilldela om parametrarna till samma variabler med de valideringsattribut som krävs. Detta fungerar för både statiska metoder och instansmetoder. Ett exempel på det här mönstret finns i Exempel 4.
  2. Använd Update-TypeData för att definiera en ScriptMethod som använder valideringsattribut på parametrarna direkt. Detta fungerar bara för instansmetoder. Mer information finns i avsnittet Definiera instansmetoder med Update-TypeData .

Automatiska variabler i metoder

Alla automatiska variabler är inte tillgängliga i metoder. Följande lista innehåller automatiska variabler och förslag på om och hur du använder dem i PowerShell-klassmetoder. Automatiska variabler som inte ingår i listan är inte tillgängliga för klassmetoder.

  • $? - Åtkomst som vanligt.
  • $_ - Åtkomst som vanligt.
  • $args – Använd explicita parametervariabler i stället.
  • $ConsoleFileName – Åtkomst som $Script:ConsoleFileName i stället.
  • $Error - Åtkomst som vanligt.
  • $EnabledExperimentalFeatures – Åtkomst som $Script:EnabledExperimentalFeatures i stället.
  • $Event - Åtkomst som vanligt.
  • $EventArgs - Åtkomst som vanligt.
  • $EventSubscriber - Åtkomst som vanligt.
  • $ExecutionContext – Åtkomst som $Script:ExecutionContext i stället.
  • $false - Åtkomst som vanligt.
  • $foreach - Åtkomst som vanligt.
  • $HOME – Åtkomst som $Script:HOME i stället.
  • $Host – Åtkomst som $Script:Host i stället.
  • $input – Använd explicita parametervariabler i stället.
  • $IsCoreCLR – Åtkomst som $Script:IsCoreCLR i stället.
  • $IsLinux – Åtkomst som $Script:IsLinux i stället.
  • $IsMacOS – Åtkomst som $Script:IsMacOS i stället.
  • $IsWindows – Åtkomst som $Script:IsWindows i stället.
  • $LASTEXITCODE - Åtkomst som vanligt.
  • $Matches - Åtkomst som vanligt.
  • $MyInvocation - Åtkomst som vanligt.
  • $NestedPromptLevel - Åtkomst som vanligt.
  • $null - Åtkomst som vanligt.
  • $PID – Åtkomst som $Script:PID i stället.
  • $PROFILE – Åtkomst som $Script:PROFILE i stället.
  • $PSBoundParameters - Använd inte den här variabeln. Den är avsedd för cmdletar och funktioner. Att använda det i en klass kan ha oväntade biverkningar.
  • $PSCmdlet - Använd inte den här variabeln. Den är avsedd för cmdletar och funktioner. Att använda det i en klass kan ha oväntade biverkningar.
  • $PSCommandPath - Åtkomst som vanligt.
  • $PSCulture – Åtkomst som $Script:PSCulture i stället.
  • $PSEdition – Åtkomst som $Script:PSEdition i stället.
  • $PSHOME – Åtkomst som $Script:PSHOME i stället.
  • $PSItem - Åtkomst som vanligt.
  • $PSScriptRoot - Åtkomst som vanligt.
  • $PSSenderInfo – Åtkomst som $Script:PSSenderInfo i stället.
  • $PSUICulture – Åtkomst som $Script:PSUICulture i stället.
  • $PSVersionTable – Åtkomst som $Script:PSVersionTable i stället.
  • $PWD - Åtkomst som vanligt.
  • $Sender - Åtkomst som vanligt.
  • $ShellId – Åtkomst som $Script:ShellId i stället.
  • $StackTrace - Åtkomst som vanligt.
  • $switch - Åtkomst som vanligt.
  • $this - Åtkomst som vanligt. I en klassmetod $this är alltid den aktuella instansen av klassen. Du kan komma åt klassegenskaperna och metoderna med den. Den är inte tillgänglig i statiska metoder.
  • $true - Åtkomst som vanligt.

Mer information om automatiska variabler finns i about_Automatic_Variables.

Dolda metoder

Du kan dölja metoder för en klass genom att deklarera dem med nyckelordet hidden . Dolda klassmetoder är:

  • Ingår inte i listan över klassmedlemmar som returneras av cmdleten Get-Member . Om du vill visa dolda metoder med Get-Memberanvänder du parametern Force .
  • Visas inte i tabbslut eller IntelliSense om inte slutförandet sker i klassen som definierar den dolda metoden.
  • Offentliga medlemmar i klassen. De kan anropas och ärvas. Att dölja en metod gör den inte privat. Den döljer bara metoden enligt beskrivningen i föregående punkter.

Kommentar

När du döljer eventuell överlagring för en metod tas den metoden bort från IntelliSense, slutföranderesultat och standardutdata för Get-Member.

Mer information om nyckelordet finns i hidden about_Hidden.

Statiska metoder

Du kan definiera en metod som tillhör själva klassen i stället för instanser av klassen genom att deklarera metoden med nyckelordet static . Statiska klassmetoder:

  • Är alltid tillgängliga, oberoende av klass-instansiering.
  • Delas mellan alla instanser av klassen.
  • Är alltid tillgängliga.
  • Det går inte att komma åt klassens instansegenskaper. De kan bara komma åt statiska egenskaper.
  • Live under hela sessionsintervallet.

Härledda klassmetoder

När en klass härleds från en basklass ärver den metoderna för basklassen och deras överlagringar. Alla metodöverlagringar som definierats i basklassen, inklusive dolda metoder, är tillgängliga för den härledda klassen.

En härledd klass kan åsidosätta en ärvd metodöverbelastning genom att omdefiniera den i klassdefinitionen. Om du vill åsidosätta överlagringen måste parametertyperna vara samma som för basklassen. Utdatatypen för överlagringen kan vara annorlunda.

Till skillnad från konstruktorer kan metoder inte använda syntaxen : base(<parameters>) för att anropa en basklassöverlagring för metoden. Den omdefinierade överbelastningen på den härledda klassen ersätter helt den överlagring som definieras av basklassen.

I följande exempel visas beteendet för statiska metoder och instansmetoder i härledda klasser.

Basklassen definierar:

  • De statiska metoderna Now() för att returnera den aktuella tiden och DaysAgo() för att returnera ett datum tidigare.
  • Instansegenskapen TimeStamp och en ToString() instansmetod som returnerar strängrepresentationen av den egenskapen. Detta säkerställer att när en instans används i en sträng konverteras den till datetime-strängen i stället för klassnamnet.
  • Instansmetoden SetTimeStamp() med två överlagringar. När metoden anropas utan parametrar ställer den in TimeStamp till aktuell tid. När metoden anropas med en DateTime ställer den in TimeStamp till det värdet.
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()
    }
}

Nästa block definierar klasser som härleds från BaseClass:

  • DerivedClassA ärver från BaseClass utan några åsidosättningar.
  • DerivedClassB åsidosätter den DaysAgo() statiska metoden för att returnera en strängrepresentation i stället för DateTime-objektet . Den åsidosätter ToString() också instansmetoden för att returnera tidsstämpeln som en ISO8601 datumsträng.
  • DerivedClassC åsidosätter metodens parameterlösa överbelastning SetTimeStamp() så att inställningen av tidsstämpeln utan parametrar anger datumet till 10 dagar före det aktuella datumet.
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))
    }
}

Följande block visar utdata från den statiska Now() metoden för de definierade klasserna. Utdata är desamma för varje klass eftersom de härledda klasserna inte åsidosätter metodens grundläggande klassimplementering.

"[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

Nästa block anropar den DaysAgo() statiska metoden för varje klass. Endast utdata för DerivedClassB skiljer sig eftersom den överskrör basimplementeringen.

"[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

Följande block visar strängpresentationen för en ny instans för varje klass. Representationen för DerivedClassB skiljer sig eftersom instansmetoden överskrids ToString() .

"`$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

Nästa block anropar SetTimeStamp() instansmetoden för varje instans och anger egenskapen TimeStamp till ett specifikt datum. Varje instans har samma datum eftersom ingen av de härledda klasserna åsidosätter den parametriserade överbelastningen för metoden.

[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

Det sista blocket anropar SetTimeStamp() utan några parametrar. Utdata visar att värdet för DerivedClassC-instansen är inställt på 10 dagar före de andra.

"`$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

Definiera instansmetoder med Update-TypeData

Förutom att deklarera metoder direkt i klassdefinitionen kan du definiera metoder för instanser av en klass i den statiska konstruktorn med hjälp av cmdleten Update-TypeData .

Använd det här kodfragmentet som utgångspunkt för mönstret. Ersätt platshållartexten i vinkelparenteser efter behov.

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
        }
    }
}

Dricks

Cmdleten Add-Member kan lägga till egenskaper och metoder i en klass i icke-statiska konstruktorer, men cmdleten körs varje gång konstruktorn anropas. Om du använder Update-TypeData den statiska konstruktorn ser du till att koden för att lägga till medlemmar i klassen bara behöver köras en gång i en session.

Definiera metoder med standardparametervärden och valideringsattribut

Metoder som definieras direkt i en klassdeklaration kan inte definiera standardvärden eller valideringsattribut för metodparametrarna. Om du vill definiera klassmetoder med standardvärden eller valideringsattribut måste de definieras som ScriptMethod-medlemmar .

I det här exemplet definierar klassen CardDeck en Draw() metod som använder både ett valideringsattribut och ett standardvärde för parametern 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.

Kommentar

Det här mönstret fungerar för valideringsattribut, men observera att undantaget är missvisande och refererar till en oförmåga att lägga till ett attribut. Det kan vara en bättre användarupplevelse att uttryckligen kontrollera värdet för parametern och skapa ett meningsfullt fel i stället. På så sätt kan användarna förstå varför de ser felet och vad de ska göra åt det.

Begränsningar

PowerShell-klassmetoder har följande begränsningar:

  • Metodparametrar kan inte använda några attribut, inklusive valideringsattribut.

    Lösning: Tilldela om parametrarna i metodtexten med valideringsattributet eller definiera metoden i den statiska konstruktorn med cmdleten Update-TypeData .

  • Metodparametrar kan inte definiera standardvärden. Parametrarna är alltid obligatoriska.

    Lösning: Definiera metoden i den statiska konstruktorn med cmdleten Update-TypeData .

  • Metoder är alltid offentliga, även när de är dolda. De kan åsidosättas när klassen ärvs.

    Lösning: Inga.

  • Om någon överlagring av en metod är dold behandlas även varje överlagring för den metoden som dold.

    Lösning: Inga.

Se även