about_Classes_Methods

Kurze Beschreibung

Beschreibt, wie Methoden für PowerShell-Klassen definiert werden.

Lange Beschreibung

Methoden definieren die Aktionen, die von einer Klasse ausgeführt werden können. Methoden können Parameter verwenden, die Eingabedaten angeben. Methoden definieren immer einen Ausgabetyp. Wenn eine Methode keine Ausgabe zurückgibt, muss sie den Ausgabetyp "Void" aufweisen. Wenn eine Methode keinen Ausgabetyp explizit definiert, lautet der Ausgabetyp der Methode "Void".

In Klassenmethoden werden keine Objekte an die Pipeline gesendet, mit Ausnahme der in der return Anweisung angegebenen. Es gibt keine versehentliche Ausgabe für die Pipeline aus dem Code.

Hinweis

Dies unterscheidet sich grundlegend davon, wie PowerShell-Funktionen die Ausgabe verarbeiten, wo alles an die Pipeline geht.

Nicht bestimmter Fehler, die aus einer Klassenmethode in den Fehlerdatenstrom geschrieben wurden, werden nicht übergeben. Sie müssen verwenden throw , um einen Beendigungsfehler anzuzeigen. Mit den Write-* Cmdlets können Sie weiterhin in die Ausgabedatenströme von PowerShell aus einer Klassenmethode schreiben. Die Cmdlets respektieren die Einstellungsvariablen im aufrufenden Bereich. Sie sollten die Verwendung der Write-* Cmdlets jedoch vermeiden, damit die Methode nur Objekte mit der return Anweisung ausgibt.

Klassenmethoden können auf die aktuelle Instanz des Klassenobjekts verweisen, indem die $this automatische Variable verwendet wird, um auf Eigenschaften und andere Methoden zuzugreifen, die in der aktuellen Klasse definiert sind. Die $this automatische Variable ist in statischen Methoden nicht verfügbar.

Klassenmethoden können eine beliebige Anzahl von Attributen aufweisen, einschließlich der ausgeblendeten und statischen Attribute.

Syntax

Klassenmethoden verwenden die folgenden Syntaxen:

Einzeilige Syntax

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

Mehrzeilige Syntax

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

Beispiele

Beispiel 1 – Minimale Methodendefinition

Die GetVolume() Methode der ExampleCube1-Klasse gibt das Volumen des Cubes zurück. Er definiert den Ausgabetyp als unverankerte Zahl und gibt das Ergebnis der Multiplikation der Eigenschaften Height, Length und Width der Instanz zurück.

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

Beispiel 2 – Methode mit Parametern

Die GeWeight() Methode verwendet eine unverankerte Zahleneingabe für die Dichte des Würfels und gibt die Gewichtung des Würfels zurück, berechnet als Volumen multipliziert mit Dichte.

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

Beispiel 3 – Methode ohne Ausgabe

In diesem Beispiel wird die Validate() Methode mit dem Ausgabetyp " System.Void" definiert. Diese Methode gibt keine Ausgabe zurück. Wenn die Überprüfung fehlschlägt, wird stattdessen ein Fehler ausgelöst. Die GetVolume() Methode ruft vor der Berechnung des Volumens des Cubes auf Validate() . Wenn die Überprüfung fehlschlägt, wird die Methode vor der Berechnung beendet.

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.

Die Methode löst eine Ausnahme aus, da die Eigenschaften "Height " und "Width " ungültig sind und verhindern, dass die Klasse das aktuelle Volume berechnet.

Beispiel 4 : Statische Methode mit Überladungen

Die ExampleCube4-Klasse definiert die statische Methode GetVolume() mit zwei Überladungen. Die erste Überladung enthält Parameter für die Dimensionen des Cubes und ein Flag, um anzugeben, ob die Methode die Eingabe überprüfen soll.

Die zweite Überladung enthält nur die numerischen Eingaben. Sie ruft die erste Überladung mit $Static als $true. Die zweite Überladung bietet Benutzern eine Möglichkeit, die Methode aufzurufen, ohne immer zu definieren, ob die Eingabe streng überprüft werden soll.

Die Klasse definiert GetVolume() auch als Instanz (nicht statische) Methode. Diese Methode ruft die zweite statische Überladung auf, um sicherzustellen, dass die Instanzmethode GetVolume() immer die Dimensionen des Cubes überprüft, bevor der Ausgabewert zurückgegeben wird.

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.

Die ausführlichen Meldungen in den Methodendefinitionen zeigen, wie der anfängliche Aufruf der $this.GetVolume() statischen Methode aufgerufen wird.

Direktes Aufrufen der statischen Methode mit dem Strict-Parameter als $false Rückgabe 0 für das Volume.

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

Methodensignaturen und -überladungen

Jede Klassenmethode verfügt über eine eindeutige Signatur, die definiert, wie die Methode aufgerufen wird. Der Ausgabetyp, der Name und die Parameter der Methode definieren die Methodensignatur.

Wenn eine Klasse mehrere Methoden mit demselben Namen definiert, sind die Definitionen dieser Methode Überladungen. Überladungen für eine Methode müssen unterschiedliche Parameter aufweisen. Eine Methode kann nicht zwei Implementierungen mit denselben Parametern definieren, auch wenn die Ausgabetypen unterschiedlich sind.

Die folgende Klasse definiert zwei Methoden Shuffle() und Deal(). Die Deal() Methode definiert zwei Überladungen, eine ohne Parameter und die andere mit dem Count-Parameter .

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

Methodenausgabe

Standardmäßig haben Methoden keine Ausgabe. Wenn eine Methodensignatur einen anderen ausgabetyp als Void enthält, muss die Methode ein Objekt dieses Typs zurückgeben. Methoden geben keine Ausgabe aus, außer wenn die return Schlüsselwort (keyword) explizit ein Objekt zurückgibt.

Methodenparameter

Klassenmethoden können Eingabeparameter definieren, die im Methodentext verwendet werden sollen. Methodenparameter werden in Klammern eingeschlossen und durch Kommas getrennt. Leere Klammern geben an, dass für die Methode keine Parameter erforderlich sind.

Parameter können in einer einzelnen Zeile oder mehreren Zeilen definiert werden. Die folgenden Blöcke zeigen die Syntax für Methodenparameter.

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

Methodenparameter können stark typiert werden. Wenn kein Parameter eingegeben wird, akzeptiert die Methode ein Objekt für diesen Parameter. Wenn der Parameter eingegeben wird, versucht die Methode, den Wert für diesen Parameter in den richtigen Typ zu konvertieren, und löst eine Ausnahme aus, wenn die Eingabe nicht konvertiert werden kann.

Methodenparameter können keine Standardwerte definieren. Alle Methodenparameter sind obligatorisch.

Methodenparameter können keine anderen Attribute aufweisen. Dadurch wird verhindert, dass Methoden Parameter mit den Validate* Attributen verwenden. Weitere Informationen zu den Überprüfungsattributen finden Sie unter about_Functions_Advanced_Parameters.

Sie können eines der folgenden Muster verwenden, um Methodenparametern eine Überprüfung hinzuzufügen:

  1. Weisen Sie die Parameter den gleichen Variablen mit den erforderlichen Überprüfungsattributen neu zu. Dies funktioniert sowohl für statische als auch für Instanzmethoden. Ein Beispiel für dieses Muster finden Sie unter Beispiel 4.
  2. Dient Update-TypeData zum Definieren einer ScriptMethod Eigenschaft, die Validierungsattribute für die Parameter direkt verwendet. Dies funktioniert nur für Instanzenmethoden. Weitere Informationen finden Sie im Abschnitt "Definieren von Instanzmethoden mit Update-TypeData ".

Automatische Variablen in Methoden

Nicht alle automatischen Variablen sind in Methoden verfügbar. Die folgende Liste enthält automatische Variablen und Vorschläge für die Verwendung in PowerShell-Klassenmethoden. Automatische Variablen, die nicht in der Liste enthalten sind, sind für Klassenmethoden nicht verfügbar.

  • $? - Zugriff als normal.
  • $_ - Zugriff als normal.
  • $args - Verwenden Sie stattdessen die expliziten Parametervariablen.
  • $ConsoleFileName – Stattdessen zugriff $Script:ConsoleFileName .
  • $Error - Zugriff als normal.
  • $EnabledExperimentalFeatures – Stattdessen zugriff $Script:EnabledExperimentalFeatures .
  • $Event - Zugriff als normal.
  • $EventArgs - Zugriff als normal.
  • $EventSubscriber - Zugriff als normal.
  • $ExecutionContext – Stattdessen zugriff $Script:ExecutionContext .
  • $false - Zugriff als normal.
  • $foreach - Zugriff als normal.
  • $HOME – Stattdessen zugriff $Script:HOME .
  • $Host – Stattdessen zugriff $Script:Host .
  • $input - Verwenden Sie stattdessen die expliziten Parametervariablen.
  • $IsCoreCLR – Stattdessen zugriff $Script:IsCoreCLR .
  • $IsLinux – Stattdessen zugriff $Script:IsLinux .
  • $IsMacOS – Stattdessen zugriff $Script:IsMacOS .
  • $IsWindows – Stattdessen zugriff $Script:IsWindows .
  • $LASTEXITCODE - Zugriff als normal.
  • $Matches - Zugriff als normal.
  • $MyInvocation - Zugriff als normal.
  • $NestedPromptLevel - Zugriff als normal.
  • $null - Zugriff als normal.
  • $PID – Stattdessen zugriff $Script:PID .
  • $PROFILE – Stattdessen zugriff $Script:PROFILE .
  • $PSBoundParameters - Verwenden Sie diese Variable nicht. Sie ist für Cmdlets und Funktionen vorgesehen. Die Verwendung in einer Klasse kann unerwartete Nebenwirkungen haben.
  • $PSCmdlet - Verwenden Sie diese Variable nicht. Sie ist für Cmdlets und Funktionen vorgesehen. Die Verwendung in einer Klasse kann unerwartete Nebenwirkungen haben.
  • $PSCommandPath - Zugriff als normal.
  • $PSCulture – Stattdessen zugriff $Script:PSCulture .
  • $PSEdition – Stattdessen zugriff $Script:PSEdition .
  • $PSHOME – Stattdessen zugriff $Script:PSHOME .
  • $PSItem - Zugriff als normal.
  • $PSScriptRoot - Zugriff als normal.
  • $PSSenderInfo – Stattdessen zugriff $Script:PSSenderInfo .
  • $PSUICulture – Stattdessen zugriff $Script:PSUICulture .
  • $PSVersionTable – Stattdessen zugriff $Script:PSVersionTable .
  • $PWD - Zugriff als normal.
  • $Sender - Zugriff als normal.
  • $ShellId – Stattdessen zugriff $Script:ShellId .
  • $StackTrace - Zugriff als normal.
  • $switch - Zugriff als normal.
  • $this - Zugriff als normal. In einer Klassenmethode $this ist immer die aktuelle Instanz der Klasse. Sie können damit auf die Klasseneigenschaften und -methoden zugreifen. Sie ist in statischen Methoden nicht verfügbar.
  • $true - Zugriff als normal.

Weitere Informationen zu automatischen Variablen finden Sie unter about_Automatic_Variables.

Ausgeblendete Methoden

Sie können Methoden einer Klasse ausblenden, indem Sie sie mit dem hidden Schlüsselwort (keyword) deklarieren. Ausgeblendete Klassenmethoden sind:

  • Nicht in der Liste der vom Cmdlet zurückgegebenen Get-Member Klassenmber enthalten. Um ausgeblendete Methoden mit Get-Memberanzuzeigen, verwenden Sie den Parameter Force .
  • Wird nicht im Abschluss der Registerkarte oder IntelliSense angezeigt, es sei denn, der Abschluss erfolgt in der Klasse, die die ausgeblendete Methode definiert.
  • Öffentliche Member der Klasse. Sie können aufgerufen und geerbt werden. Durch das Ausblenden einer Methode wird sie nicht privat. Sie blendet die Methode nur aus, wie in den vorherigen Punkten beschrieben.

Hinweis

Wenn Sie eine Überladung für eine Methode ausblenden, wird diese Methode aus IntelliSense, Abschlussergebnissen und der Standardausgabe für Get-Member.

Weitere Informationen zum hidden Schlüsselwort (keyword) finden Sie unter about_Hidden.

Statische Methoden

Sie können eine Methode als Zugehörigkeit zur Klasse selbst und nicht als Instanzen der Klasse definieren, indem Sie die Methode mit dem static Schlüsselwort (keyword) deklarieren. Statische Klassenmethoden:

  • Sind immer verfügbar, unabhängig von der Klasseninstanziierung.
  • Werden für alle Instanzen der Klasse freigegeben.
  • Sind immer verfügbar.
  • Auf Instanzeigenschaften der Klasse kann nicht zugegriffen werden. Sie können nur auf statische Eigenschaften zugreifen.
  • Live für die gesamte Sitzungsspanne.

Abgeleitete Klassenmethoden

Wenn eine Klasse von einer Basisklasse abgeleitet wird, erbt sie die Methoden der Basisklasse und deren Überladungen. Alle für die Basisklasse definierten Methodenüberladungen, einschließlich ausgeblendeter Methoden, sind für die abgeleitete Klasse verfügbar.

Eine abgeleitete Klasse kann eine geerbte Methodenüberladung überschreiben, indem sie in der Klassendefinition neu definiert wird. Um die Überladung außer Kraft zu setzen, müssen die Parametertypen mit der Basisklasse identisch sein. Der Ausgabetyp für die Überladung kann unterschiedlich sein.

Im Gegensatz zu Konstruktoren können Methoden die : base(<parameters>) Syntax nicht verwenden, um eine Basisklassenüberladung für die Methode aufzurufen. Die neu definierte Überladung für die abgeleitete Klasse ersetzt die durch die Basisklasse definierte Überladung vollständig.

Das folgende Beispiel zeigt das Verhalten für statische und Instanzmethoden für abgeleitete Klassen.

Die Basisklasse definiert Folgendes:

  • Die statischen Methoden Now() zum Zurückgeben der aktuellen Uhrzeit und DaysAgo() zum Zurückgeben eines Datums in der Vergangenheit.
  • Die Instanzeigenschaft TimeStamp und eine ToString() Instanzmethode, die die Zeichenfolgendarstellung dieser Eigenschaft zurückgibt. Dadurch wird sichergestellt, dass beim Verwenden einer Instanz in einer Zeichenfolge anstelle des Klassennamens in die Datetime-Zeichenfolge konvertiert wird.
  • Die Instanzmethode SetTimeStamp() mit zwei Überladungen. Wenn die Methode ohne Parameter aufgerufen wird, wird der TimeStamp auf die aktuelle Uhrzeit festgelegt. Wenn die Methode mit einer DateTime aufgerufen wird, wird der TimeStamp auf diesen Wert festgelegt.
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()
    }
}

Der nächste Block definiert Klassen, die von BaseClass abgeleitet wurden:

  • DerivedClassA erbt von BaseClass ohne Außerkraftsetzungen.
  • DerivedClassB überschreibt die DaysAgo() statische Methode, um eine Zeichenfolgendarstellung anstelle des DateTime-Objekts zurückzugeben. Außerdem überschreibt sie die ToString() Instanzmethode, um den Zeitstempel als ISO8601 Datumszeichenfolge zurückzugeben.
  • DerivedClassC überschreibt die parameterlose Überladung der SetTimeStamp() Methode, sodass das Festlegen des Zeitstempels ohne Parameter das Datum auf 10 Tage vor dem aktuellen Datum festlegt.
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))
    }
}

Der folgende Block zeigt die Ausgabe der statischen Now() Methode für die definierten Klassen. Die Ausgabe ist für jede Klasse identisch, da die abgeleiteten Klassen die Basisklassenimplementierung der Methode nicht überschreiben.

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

Der nächste Block ruft die DaysAgo() statische Methode jeder Klasse auf. Nur die Ausgabe für DerivedClassB unterscheidet sich, da sie die Basisimplementierung überlasten.

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

Der folgende Block zeigt die Zeichenfolgenpräsentation einer neuen Instanz für jede Klasse. Die Darstellung für DerivedClassB unterscheidet sich, da sie die ToString() Instanzmethode überschreiben.

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

Der nächste Block ruft die SetTimeStamp() Instanzmethode für jede Instanz auf, wobei die TimeStamp-Eigenschaft auf ein bestimmtes Datum festgelegt wird. Jede Instanz hat dasselbe Datum, da keine der abgeleiteten Klassen die parametrisierte Überladung für die Methode außer Kraft setzt.

[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

Der letzte Blockaufruf SetTimeStamp() ohne Parameter. Die Ausgabe zeigt, dass der Wert für die DerivedClassC-Instanz auf 10 Tage vor den anderen festgelegt ist.

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

Definieren von Instanzmethoden mit Update-TypeData

Über das direkte Deklarieren von Methoden in der Klassendefinition hinaus können Sie Methoden für Instanzen einer Klasse im statischen Konstruktor mithilfe des Update-TypeData Cmdlets definieren.

Verwenden Sie diesen Codeausschnitt als Ausgangspunkt für das Muster. Ersetzen Sie den Platzhaltertext nach Bedarf in winkeln Klammern.

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

Tipp

Das Add-Member Cmdlet kann einer Klasse in nicht statischen Konstruktoren Eigenschaften und Methoden hinzufügen, das Cmdlet wird jedoch jedes Mal ausgeführt, wenn der Konstruktor aufgerufen wird. Die Verwendung Update-TypeData im statischen Konstruktor stellt sicher, dass der Code zum Hinzufügen der Member zur Klasse nur einmal in einer Sitzung ausgeführt werden muss.

Definieren von Methoden mit Standardparameterwerten und Validierungsattributen

Methoden, die direkt in einer Klassendeklaration definiert sind, können keine Standardwerte oder Überprüfungsattribute für die Methodenparameter definieren. Um Klassenmethoden mit Standardwerten oder Überprüfungsattributen zu definieren, müssen sie als ScriptMethod-Member definiert werden.

In diesem Beispiel definiert die CardDeck-Klasse eine Draw() Methode, die sowohl ein Überprüfungsattribut als auch einen Standardwert für den Count-Parameter verwendet.

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.

Hinweis

Dieses Muster funktioniert zwar für Überprüfungsattribute, beachten Sie jedoch, dass die Ausnahme irreführend ist und auf eine Unfähigkeit verweist, ein Attribut hinzuzufügen. Möglicherweise ist es eine bessere Benutzererfahrung, den Wert für den Parameter explizit zu überprüfen und stattdessen einen sinnvollen Fehler auszuheben. Auf diese Weise können Benutzer verstehen, warum sie den Fehler sehen und was sie tun müssen.

Begrenzungen

PowerShell-Klassenmethoden weisen die folgenden Einschränkungen auf:

  • Methodenparameter können keine Attribute verwenden, einschließlich Überprüfungsattributen.

    Problemumgehung: Ordnen Sie die Parameter im Methodentext erneut mit dem Überprüfungsattribut zu, oder definieren Sie die Methode im statischen Konstruktor mit dem Update-TypeData Cmdlet.

  • Methodenparameter können keine Standardwerte definieren. Die Parameter sind immer obligatorisch.

    Problemumgehung: Definieren Sie die Methode im statischen Konstruktor mit dem Update-TypeData Cmdlet.

  • Methoden sind immer öffentlich, auch wenn sie ausgeblendet sind. Sie können überschrieben werden, wenn die Klasse geerbt wird.

    Abhilfen: Keine.

  • Wenn eine Überladung einer Methode ausgeblendet ist, wird jede Überladung für diese Methode ebenfalls als ausgeblendet behandelt.

    Abhilfen: Keine.

Weitere Informationen