Delen via


about_Classes_Methods

Korte beschrijving

Hierin wordt beschreven hoe u methoden definieert voor PowerShell-klassen.

Lange beschrijving

Methoden definiëren de acties die een klasse kan uitvoeren. Methoden kunnen parameters gebruiken waarmee invoergegevens worden opgegeven. Methoden definiëren altijd een uitvoertype. Als een methode geen uitvoer retourneert, moet deze het uitvoertype Void hebben. Als een methode niet expliciet een uitvoertype definieert, is het uitvoertype van de methode Void.

In klassemethoden worden er geen objecten verzonden naar de pijplijn, behalve de objecten die zijn opgegeven in de return instructie. Er is geen onbedoelde uitvoer naar de pijplijn vanuit de code.

Notitie

Dit verschilt van de manier waarop PowerShell-functies uitvoer verwerken, waarbij alles naar de pijplijn gaat.

Niet-bepalende fouten die vanuit een klassemethode naar de foutstroom worden geschreven, worden niet doorgegeven. U moet een throw afsluitfout weergeven. Met behulp van de Write-* cmdlets kunt u nog steeds schrijven naar de uitvoerstromen van PowerShell vanuit een klassemethode. De cmdlets respecteren de voorkeursvariabelen in het aanroepende bereik. U moet echter voorkomen dat u de Write-* cmdlets gebruikt, zodat de methode alleen objecten uitvoert met behulp van de return instructie.

Klassemethoden kunnen verwijzen naar het huidige exemplaar van het klasseobject met behulp van de $this automatische variabele voor toegang tot eigenschappen en andere methoden die zijn gedefinieerd in de huidige klasse. De $this automatische variabele is niet beschikbaar in statische methoden.

Klassemethoden kunnen een willekeurig aantal kenmerken hebben, waaronder de verborgen en statische kenmerken.

Syntaxis

Klassemethoden gebruiken de volgende syntaxis:

Syntaxis van één regel

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

Syntaxis met meerdere regels

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

Voorbeelden

Voorbeeld 1: Definitie van minimale methode

De GetVolume() methode van de klasse ExampleCube1 retourneert het volume van de kubus. Het definieert het uitvoertype als een zwevend getal en retourneert het resultaat van het vermenigvuldigen van de eigenschappen Height, Length en Width van het exemplaar.

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

Voorbeeld 2: methode met parameters

De GeWeight() methode gebruikt een zwevende getalinvoer voor de dichtheid van de kubus en retourneert het gewicht van de kubus, berekend als volume vermenigvuldigd met dichtheid.

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

Voorbeeld 3: methode zonder uitvoer

In dit voorbeeld wordt de Validate() methode gedefinieerd met het uitvoertype System.Void. Deze methode retourneert geen uitvoer. Als de validatie mislukt, treedt er een fout op. De GetVolume() methode roept aan Validate() voordat het volume van de kubus wordt berekend. Als de validatie mislukt, wordt de methode beëindigd vóór de berekening.

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

Invalid cube properties ('Height', 'Width'): Cube dimensions must all be
positive numbers.
At C:\code\classes.examples.ps1:26 char:13
+             throw $Message
+             ~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Invalid cube pr...sitive
    numbers.:String) [], RuntimeException
    + FullyQualifiedErrorId : Invalid cube properties ('Height', 'Width')
   : Cube dimensions must all be positive numbers.

De methode genereert een uitzondering omdat de eigenschappen Hoogte en Breedte ongeldig zijn, waardoor de klasse het huidige volume niet kan berekenen.

Voorbeeld 4: statische methode met overbelastingen

De klasse ExampleCube4 definieert de statische methode GetVolume() met twee overbelastingen. De eerste overbelasting bevat parameters voor de dimensies van de kubus en een vlag om aan te geven of de methode de invoer moet valideren.

De tweede overbelasting bevat alleen de numerieke invoer. Het noemt de eerste overbelasting met $Static als $true. De tweede overbelasting biedt gebruikers een manier om de methode aan te roepen zonder altijd te hoeven definiëren of de invoer strikt moet worden gevalideerd.

De klasse definieert GetVolume() ook als een instantiemethode (niet-statisch). Met deze methode wordt de tweede statische overbelasting aangeroepen, zodat de instantiemethode GetVolume() altijd de dimensies van de kubus valideert voordat de uitvoerwaarde wordt geretourneerd.

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)

The variable cannot be validated because the value 0 is not a valid value
for the Width variable.
At C:\code\classes.examples.ps1:19 char:13
+             [ValidateScript({$_ -gt 0 })]$Width  = $Width
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataEx
   ception
    + FullyQualifiedErrorId : ValidateSetFailure

De uitgebreide berichten in de methodedefinities laten zien hoe de initiële aanroep voor het aanroepen van $this.GetVolume() de statische methode.

Het aanroepen van de statische methode rechtstreeks met de parameter Strict als $false retourneert 0 voor het volume.

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

Methodehandtekeningen en overbelastingen

Elke klassemethode heeft een unieke handtekening waarmee wordt gedefinieerd hoe de methode moet worden aangeroepen. Het uitvoertype, de naam en de parameters van de methode definiëren de handtekening van de methode.

Wanneer een klasse meer dan één methode met dezelfde naam definieert, zijn de definities van die methode overbelast. Overbelastingen voor een methode moeten verschillende parameters hebben. Een methode kan geen twee implementaties met dezelfde parameters definiëren, zelfs niet als de uitvoertypen verschillend zijn.

De volgende klasse definieert twee methoden en Shuffle() Deal(). De Deal() methode definieert twee overbelastingen, één zonder parameters en de andere met de parameter 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() })
    }
}

Methode-uitvoer

Standaard hebben methoden geen uitvoer. Als een methodehandtekening een ander expliciet uitvoertype dan Void bevat, moet de methode een object van dat type retourneren. Methoden verzenden geen uitvoer, behalve wanneer het return trefwoord expliciet een object retourneert.

Methodeparameters

Klassemethoden kunnen invoerparameters definiëren die moeten worden gebruikt in de hoofdtekst van de methode. Methodeparameters staan tussen haakjes en worden gescheiden door komma's. Lege haakjes geven aan dat voor de methode geen parameters zijn vereist.

Parameters kunnen worden gedefinieerd op één regel of meerdere regels. In de volgende blokken ziet u de syntaxis voor methodeparameters.

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

Methodeparameters kunnen sterk worden getypt. Als een parameter niet is getypt, accepteert de methode een object voor die parameter. Als de parameter is getypt, probeert de methode de waarde voor die parameter te converteren naar het juiste type, waardoor er een uitzondering wordt gegenereerd als de invoer niet kan worden geconverteerd.

Methodeparameters kunnen geen standaardwaarden definiëren. Alle methodeparameters zijn verplicht.

Methodeparameters kunnen geen andere kenmerken hebben. Hiermee voorkomt u dat methoden parameters met de Validate* kenmerken gebruiken. Zie about_Functions_Advanced_Parameters voor meer informatie over de validatiekenmerken.

U kunt een van de volgende patronen gebruiken om validatie toe te voegen aan methodeparameters:

  1. Wijs de parameters opnieuw toe aan dezelfde variabelen met de vereiste validatiekenmerken. Dit werkt voor zowel statische als instantiemethoden. Zie voorbeeld 4 voor een voorbeeld van dit patroon.
  2. Gebruik Update-TypeData dit om een ScriptMethod te definiëren die rechtstreeks gebruikmaakt van validatiekenmerken op de parameters. Dit werkt alleen voor exemplaarmethoden. Zie de sectie Exemplaarmethoden definiëren met de sectie Update-TypeData voor meer informatie.

Automatische variabelen in methoden

Niet alle automatische variabelen zijn beschikbaar in methoden. De volgende lijst bevat automatische variabelen en suggesties voor het gebruik ervan in PowerShell-klassenmethoden. Automatische variabelen die niet in de lijst zijn opgenomen, zijn niet beschikbaar voor klassemethoden.

  • $? - Toegang als normaal.
  • $_ - Toegang als normaal.
  • $args - Gebruik in plaats daarvan de expliciete parametervariabelen.
  • $ConsoleFileName - Toegang zoals $Script:ConsoleFileName in plaats daarvan.
  • $Error - Toegang als normaal.
  • $Event - Toegang als normaal.
  • $EventArgs - Toegang als normaal.
  • $EventSubscriber - Toegang als normaal.
  • $ExecutionContext - Toegang zoals $Script:ExecutionContext in plaats daarvan.
  • $false - Toegang als normaal.
  • $foreach - Toegang als normaal.
  • $HOME - Toegang zoals $Script:HOME in plaats daarvan.
  • $Host - Toegang zoals $Script:Host in plaats daarvan.
  • $input - Gebruik in plaats daarvan de expliciete parametervariabelen.
  • $LASTEXITCODE - Toegang als normaal.
  • $Matches - Toegang als normaal.
  • $MyInvocation - Toegang als normaal.
  • $NestedPromptLevel - Toegang als normaal.
  • $null - Toegang als normaal.
  • $PID - Toegang zoals $Script:PID in plaats daarvan.
  • $PROFILE - Toegang zoals $Script:PROFILE in plaats daarvan.
  • $PSBoundParameters - Gebruik deze variabele niet. Deze is bedoeld voor cmdlets en functies. Het gebruik ervan in een klas kan onverwachte bijwerkingen hebben.
  • $PSCmdlet - Gebruik deze variabele niet. Deze is bedoeld voor cmdlets en functies. Het gebruik ervan in een klas kan onverwachte bijwerkingen hebben.
  • $PSCommandPath - Toegang als normaal.
  • $PSCulture - Toegang zoals $Script:PSCulture in plaats daarvan.
  • $PSEdition - Toegang zoals $Script:PSEdition in plaats daarvan.
  • $PSHOME - Toegang zoals $Script:PSHOME in plaats daarvan.
  • $PSItem - Toegang als normaal.
  • $PSScriptRoot - Toegang als normaal.
  • $PSSenderInfo - Toegang zoals $Script:PSSenderInfo in plaats daarvan.
  • $PSUICulture - Toegang zoals $Script:PSUICulture in plaats daarvan.
  • $PSVersionTable - Toegang zoals $Script:PSVersionTable in plaats daarvan.
  • $PWD - Toegang als normaal.
  • $Sender - Toegang als normaal.
  • $ShellId - Toegang zoals $Script:ShellId in plaats daarvan.
  • $StackTrace - Toegang als normaal.
  • $switch - Toegang als normaal.
  • $this - Toegang als normaal. In een klassemethode $this is altijd het huidige exemplaar van de klasse. U kunt hiermee toegang krijgen tot de klasse-eigenschappen en -methoden. Het is niet beschikbaar in statische methoden.
  • $true - Toegang als normaal.

Zie about_Automatic_Variables voor meer informatie over automatische variabelen.

Verborgen methoden

U kunt methoden van een klasse verbergen door ze te declareren met het hidden trefwoord. Verborgen klassemethoden zijn:

  • Niet opgenomen in de lijst met klasseleden die door de Get-Member cmdlet worden geretourneerd. Als u verborgen methoden wilt weergeven, Get-Membergebruikt u de parameter Force .
  • Niet weergegeven in tabvoltooiing of IntelliSense, tenzij de voltooiing plaatsvindt in de klasse die de verborgen methode definieert.
  • Openbare leden van de klas. Ze kunnen worden aangeroepen en overgenomen. Het verbergen van een methode maakt het niet privé. De methode wordt alleen verborgen zoals beschreven in de vorige punten.

Notitie

Wanneer u een overbelasting voor een methode verbergt, wordt die methode verwijderd uit IntelliSense, voltooiingsresultaten en de standaarduitvoer voor Get-Member.

Zie about_Hidden voor meer informatie over het hidden trefwoord.

Statische methoden

U kunt een methode definiëren als behorend tot de klasse zelf in plaats van exemplaren van de klasse door de methode met het static trefwoord te declareren. Statische klassemethoden:

  • Zijn altijd beschikbaar, onafhankelijk van klasse-instantiëring.
  • Worden gedeeld in alle exemplaren van de klasse.
  • Zijn altijd beschikbaar.
  • Kan geen toegang krijgen tot exemplaareigenschappen van de klasse. Ze hebben alleen toegang tot statische eigenschappen.
  • Live voor het hele sessiebereik.

Afgeleide klassemethoden

Wanneer een klasse is afgeleid van een basisklasse, neemt deze de methoden van de basisklasse en hun overbelasting over. Eventuele overbelasting van methoden die zijn gedefinieerd op de basisklasse, inclusief verborgen methoden, zijn beschikbaar in de afgeleide klasse.

Een afgeleide klasse kan de overbelasting van een overgenomen methode overschrijven door deze opnieuw te definiëren in de klassedefinitie. Als u de overbelasting wilt overschrijven, moeten de parametertypen hetzelfde zijn als voor de basisklasse. Het uitvoertype voor de overbelasting kan verschillen.

In tegenstelling tot constructors kunnen methoden de : base(<parameters>) syntaxis niet gebruiken om een overbelasting van de basisklasse voor de methode aan te roepen. De opnieuw gedefinieerde overbelasting van de afgeleide klasse vervangt de overbelasting die door de basisklasse is gedefinieerd.

In het volgende voorbeeld ziet u het gedrag voor statische en exemplaarmethoden voor afgeleide klassen.

De basisklasse definieert:

  • De statische methoden Now() voor het retourneren van de huidige tijd en DaysAgo() voor het retourneren van een datum in het verleden.
  • De instantieeigenschap TimeStamp en een ToString() instantiemethode die de tekenreeksweergave van die eigenschap retourneert. Dit zorgt ervoor dat wanneer een exemplaar wordt gebruikt in een tekenreeks die wordt geconverteerd naar de datum/tijd-tekenreeks in plaats van de klassenaam.
  • De instantiemethode SetTimeStamp() met twee overbelastingen. Wanneer de methode zonder parameters wordt aangeroepen, wordt de TimeStamp ingesteld op de huidige tijd. Wanneer de methode wordt aangeroepen met een Datum/tijd, wordt de TimeStamp ingesteld op die waarde.
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()
    }
}

In het volgende blok worden klassen gedefinieerd die zijn afgeleid van BaseClass:

  • DerivedClassA neemt over van BaseClass zonder overschrijvingen.
  • DerivedClassB overschrijft de DaysAgo() statische methode om een tekenreeksweergave te retourneren in plaats van het DateTime-object . De instantiemethode wordt ook overschreven ToString() om de tijdstempel als een ISO8601 datumtekenreeks te retourneren.
  • DerivedClassC overschrijft de parameterloze overbelasting van de SetTimeStamp() methode, zodat het instellen van de tijdstempel zonder parameters de datum instelt op 10 dagen vóór de huidige datum.
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))
    }
}

In het volgende blok ziet u de uitvoer van de statische Now() methode voor de gedefinieerde klassen. De uitvoer is voor elke klasse hetzelfde, omdat de afgeleide klassen de implementatie van de basisklasse van de methode niet overschrijven.

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

In het volgende blok wordt de DaysAgo() statische methode van elke klasse aangeroepen. Alleen de uitvoer voor DerivedClassB is anders, omdat deze de basis-implementatie overroest.

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

In het volgende blok ziet u de tekenreekspresentatie van een nieuw exemplaar voor elke klasse. De weergave voor DerivedClassB is anders omdat deze de ToString() instantiemethode overroest.

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

In het volgende blok wordt de SetTimeStamp() instantiemethode voor elk exemplaar aangeroepen, waarbij de eigenschap TimeStamp wordt ingesteld op een specifieke datum. Elk exemplaar heeft dezelfde datum, omdat geen van de afgeleide klassen de geparameteriseerde overbelasting voor de methode overschrijft.

[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

De laatste blokoproepen SetTimeStamp() zonder parameters. De uitvoer laat zien dat de waarde voor het AfgeleideClassC-exemplaar is ingesteld op 10 dagen voor de andere exemplaren.

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

Exemplaarmethoden definiëren met Update-TypeData

Naast het rechtstreeks declareren van methoden in de klassedefinitie, kunt u methoden definiëren voor exemplaren van een klasse in de statische constructor met behulp van de Update-TypeData cmdlet.

Gebruik dit fragment als uitgangspunt voor het patroon. Vervang indien nodig de tekst van de tijdelijke aanduiding tussen punthaken.

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

De Add-Member cmdlet kan eigenschappen en methoden toevoegen aan een klasse in niet-statische constructors, maar de cmdlet wordt elke keer uitgevoerd wanneer de constructor wordt aangeroepen. Het gebruik Update-TypeData in de statische constructor zorgt ervoor dat de code voor het toevoegen van de leden aan de klasse slechts eenmaal in een sessie hoeft te worden uitgevoerd.

Methoden definiëren met standaardparameterwaarden en validatiekenmerken

Methoden die rechtstreeks in een klassedeclaratie zijn gedefinieerd, kunnen geen standaardwaarden of validatiekenmerken definiëren voor de methodeparameters. Als u klassemethoden met standaardwaarden of validatiekenmerken wilt definiëren, moeten ze worden gedefinieerd als ScriptMethod-leden .

In dit voorbeeld definieert de klasse CardDeck een Draw() methode die gebruikmaakt van zowel een validatiekenmerk als een standaardwaarde voor de parameter 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.

Exception calling "Eat" with "1" argument(s): "The attribute cannot be
added because variable Count with value 20 would no longer be valid."
At line:1 char:1
+ $Jar.Eat(20)
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationExcep
   tion
    + FullyQualifiedErrorId : ScriptMethodRuntimeException

You ate 6 cookies. There are 4 left.

Notitie

Hoewel dit patroon geschikt is voor validatiekenmerken, ziet u dat de uitzondering misleidend is en verwijst naar een onvermogen om een kenmerk toe te voegen. Het kan een betere gebruikerservaring zijn om expliciet de waarde voor de parameter te controleren en in plaats daarvan een zinvolle fout te genereren. Op die manier kunnen gebruikers begrijpen waarom ze de fout zien en wat ze eraan moeten doen.

Beperkingen

PowerShell-klassemethoden hebben de volgende beperkingen:

  • Methodeparameters kunnen geen kenmerken gebruiken, inclusief validatiekenmerken.

    Tijdelijke oplossing: wijs de parameters in de hoofdtekst van de methode opnieuw toe met het validatiekenmerk of definieer de methode in de statische constructor met de Update-TypeData cmdlet.

  • Methodeparameters kunnen geen standaardwaarden definiëren. De parameters zijn altijd verplicht.

    Tijdelijke oplossing: Definieer de methode in de statische constructor met de Update-TypeData cmdlet.

  • Methoden zijn altijd openbaar, zelfs als ze verborgen zijn. Ze kunnen worden overschreven wanneer de klasse wordt overgenomen.

    Oplossing: Geen.

  • Als een overbelasting van een methode verborgen is, wordt elke overbelasting voor die methode ook als verborgen behandeld.

    Oplossing: Geen.

Zie ook