about_Classes_Constructors

Kurze Beschreibung

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

Lange Beschreibung

Mit Konstruktoren können Sie Standardwerte festlegen und die Objektlogik zum Zeitpunkt der Erstellung der Instanz der Klasse überprüfen. Konstruktoren haben denselben Namen wie die Klasse. Konstruktoren verfügen möglicherweise über Parameter, um die Datenmmber des neuen Objekts zu initialisieren.

PowerShell-Klassenkonstruktoren werden als spezielle Methoden für die Klasse definiert. Sie verhalten sich mit den PowerShell-Klassenmethoden mit den folgenden Ausnahmen:

  • Konstruktoren haben keinen Ausgabetyp. Sie können die return Schlüsselwort (keyword) nicht verwenden.
  • Konstruktoren haben immer denselben Namen wie die Klasse.
  • Konstruktoren können nicht direkt aufgerufen werden. Sie werden nur ausgeführt, wenn eine Instanz erstellt wird.
  • Konstruktoren werden nie in der Ausgabe für das Get-Member Cmdlet angezeigt.

Weitere Informationen zu PowerShell-Klassenmethoden finden Sie unter about_Classes_Methods.

Die Klasse kann null oder mehr Konstruktoren definiert haben. Wenn kein Konstruktor definiert ist, erhält die Klasse einen standardparameterlosen Konstruktor. Dieser Konstruktor initialisiert alle Member mit ihren Standardwerten. Objekttypen und Zeichenfolgen werden NULL-Werte angegeben. Wenn Sie den Konstruktor definieren, wird kein standardparameterloser Konstruktor erstellt. Erstellen Sie bei Bedarf einen parameterlosen Konstruktor.

Sie können auch einen parameterlosen statischen Konstruktor definieren.

Syntax

Klassenkonstruktoren verwenden die folgenden Syntaxen:

Standardkonstruktorsyntax

<class-name> () [: base([<params>])] {
    <body>
}

Syntax statischer Konstruktor

static <class-name> () [: base([<params>])] {
    <body>
}

Parametrisierte Konstruktorsyntax (einzeilige)

<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
    <body>
}

Parametrisierte Konstruktorsyntax (multiline)

<class-name> (
    [<parameter-type>]$<parameter-name>[,
    [<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
    <body>
}

Beispiele

Beispiel 1: Definieren einer Klasse mit dem Standardkonstruktor

Die ExampleBook1-Klasse definiert keinen Konstruktor. Stattdessen wird der automatische Standardkonstruktor verwendet.

class ExampleBook1 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn
}

[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                0 1/1/0001 12:00:00 AM

Hinweis

Der Standardwert für die Eigenschaften Name und Autor besteht $null darin, dass sie als Zeichenfolgen eingegeben werden, bei denen es sich um einen Verweistyp handelt. Die anderen Eigenschaften weisen den Standardwert für ihren definierten Typ auf, da sie Werttypeigenschaften sind. Weitere Informationen zu den Standardwerten für Eigenschaften finden Sie unter "Standardwerte" in about_Classes_Properties.

Beispiel 2: Überschreiben des Standardkonstruktors

ExampleBook2 definiert explizit den Standardkonstruktor und legt die Werte für "PublishedOn " auf das aktuelle Datum und "Pages " fest 1.

class ExampleBook2 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook2() {
        $this.PublishedOn = (Get-Date).Date
        $this.Pages       = 1
    }
}

[ExampleBook2]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                1 11/1/2023 12:00:00 AM

Beispiel 3 : Definieren von Konstruktorüberladungen

Die ExampleBook3-Klasse definiert drei Konstruktorüberladungen, sodass Benutzer eine Instanz der Klasse aus einer Hashtabelle erstellen können, indem sie jeden Eigenschaftswert übergeben und den Namen des Buchs und Autors übergeben. Die Klasse definiert nicht den Standardkonstruktor.

class ExampleBook3 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook3([hashtable]$Info) {
        switch ($Info.Keys) {
            'Name'        { $this.Name        = $Info.Name }
            'Author'      { $this.Author      = $Info.Author }
            'Pages'       { $this.Pages       = $Info.Pages }
            'PublishedOn' { $this.PublishedOn = $Info.PublishedOn }
        }
    }

    ExampleBook3(
        [string]   $Name,
        [string]   $Author,
        [int]      $Pages,
        [datetime] $PublishedOn
    ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.Pages       = $Pages
        $this.PublishedOn = $PublishedOn
    }

    ExampleBook3([string]$Name, [string]$Author) {
        $this.Name   = $Name
        $this.Author = $Author
    }
}

[ExampleBook3]::new(@{
    Name        = 'The Hobbit'
    Author      = 'J.R.R. Tolkien'
    Pages       = 310
    PublishedOn = '1937-09-21'
})
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien', 310, '1937-09-21')
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook3]::new()
Name       Author         Pages PublishedOn
----       ------         ----- -----------
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien     0 1/1/0001 12:00:00 AM

MethodException:
Line |
  42 |  [ExampleBook3]::new()
     |  ~~~~~~~~~~~~~~~~~~~~~
     | Cannot find an overload for "new" and the argument count: "0".

Durch Aufrufen des Standardkonstruktors wird eine Methoden exception zurückgegeben. Der automatische Standardkonstruktor wird nur für eine Klasse definiert, wenn die Klasse keine Konstruktoren definiert. Da ExampleBook3 mehrere Überladungen definiert, wird der Standardkonstruktor nicht automatisch der Klasse hinzugefügt.

Beispiel 4 : Verketten von Konstruktoren mit einer freigegebenen Methode

In diesem Beispiel wird gezeigt, wie Sie wiederverwendbaren freigegebenen Code für Konstruktoren schreiben können. PowerShell-Klassen können keine Konstruktorkette verwenden, daher definiert diese Beispielklasse stattdessen eine Init() Methode. Für die -Methode gibt es mehrere Überladungen. Die Überladungen mit weniger Parametern rufen die expliziteren Überladungen mit Standardwerten für die nicht angegebenen Parameter auf.

class ExampleBook4 {
    [string]   $Name
    [string]   $Author
    [datetime] $PublishedOn
    [int]      $Pages

    ExampleBook4() {
        $this.Init()
    }
    ExampleBook4([string]$Name) {
        $this.Init($Name)
    }
    ExampleBook4([string]$Name, [string]$Author) {
        $this.Init($Name, $Author)
    }
    ExampleBook4([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn)
    }
    ExampleBook4(
      [string]$Name,
      [string]$Author,
      [datetime]$PublishedOn,
      [int]$Pages
    ) {
        $this.Init($Name, $Author, $PublishedOn, $Pages)
    }

    hidden Init() {
        $this.Init('Unknown')
    }
    hidden Init([string]$Name) {
        $this.Init($Name, 'Unknown')
    }
    hidden Init([string]$Name, [string]$Author) {
        $this.Init($Name, $Author, (Get-Date).Date)
    }
    hidden Init([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn, 1)
    }
    hidden Init(
        [string]$Name,
        [string]$Author,
        [datetime]$PublishedOn,
        [int]$Pages
      ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.PublishedOn = $PublishedOn
        $this.Pages       = $Pages
    }
}

[ExampleBook4]::new()
[ExampleBook4]::new('The Hobbit')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien', (Get-Date '1937-9-21'))
[ExampleBook4]::new(
    'The Hobbit',
    'J.R.R. Tolkien',
    (Get-Date '1937-9-21'),
    310
)
Name       Author         PublishedOn           Pages
----       ------         -----------           -----
Unknown    Unknown        11/1/2023 12:00:00 AM     1
The Hobbit Unknown        11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM   310

Beispiel 5 : Abgeleitete Klassenkonstruktoren

In den folgenden Beispielen werden Klassen verwendet, die die statischen, standard- und parametrisierten Konstruktoren für eine Basisklasse und eine abgeleitete Klasse definieren, die von der Basisklasse erbt.

class BaseExample {
    static [void] DefaultMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] default constructor"
    }

    static [void] StaticMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] static constructor"
    }

    static [void] ParamMessage([type]$Type, [object]$Value) {
        Write-Verbose "[$($Type.Name)] param constructor ($Value)"
    }

    static BaseExample() { [BaseExample]::StaticMessage([BaseExample])  }
    BaseExample()        { [BaseExample]::DefaultMessage([BaseExample]) }
    BaseExample($Value)  { [BaseExample]::ParamMessage([BaseExample], $Value) }
}

class DerivedExample : BaseExample {
    static DerivedExample() { [BaseExample]::StaticMessage([DerivedExample])  }
           DerivedExample() { [BaseExample]::DefaultMessage([DerivedExample]) }

    DerivedExample([int]$Number) : base($Number) {
        [BaseExample]::ParamMessage([DerivedExample], $Number)
    }
    DerivedExample([string]$String) {
        [BaseExample]::ParamMessage([DerivedExample], $String)
    }
}

Der folgende Block zeigt das ausführliche Messaging zum Aufrufen der Basisklassenkonstruktoren. Die statische Konstruktornachricht wird nur ausgegeben, wenn eine Instanz der Klasse zum ersten Mal erstellt wird.

PS> $VerbosePreference = 'Continue'
PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)

Der nächste Block zeigt das ausführliche Messaging zum Aufrufen der abgeleiteten Klassenkonstruktoren in einer neuen Sitzung. Wenn ein abgeleiteter Klassenkonstruktor zum ersten Mal aufgerufen wird, werden die statischen Konstruktoren für die Basisklasse und die abgeleitete Klasse aufgerufen. Diese Konstruktoren werden in der Sitzung nicht erneut aufgerufen. Die Konstruktoren für die Basisklasse werden immer vor den Konstruktoren für die abgeleitete Klasse ausgeführt.

PS> $VerbosePreference = 'Continue'
PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [DerivedExample] static constructor
VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)
VERBOSE: [DerivedExample] param constructor (1)

PS> $c = [DerivedExample]::new('foo')

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] param constructor (foo)

Konstruktor wird sortierung ausgeführt

Wenn eine Klasse instanziiert, wird der Code für einen oder mehrere Konstruktoren ausgeführt.

Bei Klassen, die nicht von einer anderen Klasse erben, lautet die Sortierung:

  1. Der statische Konstruktor für die Klasse.
  2. Die entsprechende Konstruktorüberladung für die Klasse.

Bei abgeleiteten Klassen, die von einer anderen Klasse erben, lautet die Sortierung:

  1. Der statische Konstruktor für die Basisklasse.
  2. Der statische Konstruktor für die abgeleitete Klasse.
  3. Wenn der abgeleitete Klassenkonstruktor explizit eine Basiskonstruktorüberladung aufruft, wird dieser Konstruktor für die Basisklasse ausgeführt. Wenn kein Basiskonstruktor explizit aufgerufen wird, wird der Standardkonstruktor für die Basisklasse ausgeführt.
  4. Die entsprechende Konstruktorüberladung für die abgeleitete Klasse.

In allen Fällen werden statische Konstruktoren nur einmal in einer Sitzung ausgeführt.

Ein Beispiel für Konstruktorverhalten und -sortierung finden Sie unter Beispiel 5.

Ausgeblendete Konstruktoren

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

  • Nicht in der Standardausgabe für die Klasse enthalten.
  • Nicht in der Liste der vom Cmdlet zurückgegebenen Get-Member Klassenmber enthalten. Um ausgeblendete Eigenschaften mit Get-Memberanzuzeigen, verwenden Sie den Force-Parameter .
  • Wird nicht im Abschluss der Registerkarte oder IntelliSense angezeigt, es sei denn, der Abschluss erfolgt in der Klasse, die die ausgeblendete Eigenschaft definiert.
  • Öffentliche Member der Klasse. Auf sie kann zugegriffen und geändert werden. Durch das Ausblenden einer Eigenschaft wird sie nicht privat. Sie blendet die Eigenschaft nur aus, wie in den vorherigen Punkten beschrieben.

Hinweis

Wenn Sie einen Konstruktor ausblenden, wird die new() Option aus IntelliSense- und Abschlussergebnissen entfernt.

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

Statische Konstruktoren

Sie können einen Konstruktor als Zugehörigkeit zur Klasse selbst und nicht als Instanzen der Klasse definieren, indem Sie den Konstruktor mit dem static Schlüsselwort (keyword) deklarieren. Statische Klassenkonstruktoren:

  • Rufen Sie nur das erste Mal auf, wenn eine Instanz der Klasse in der Sitzung erstellt wird.
  • Es können keine Parameter vorhanden sein.
  • Auf Instanzeigenschaften oder -methoden mit der $this Variablen kann nicht zugegriffen werden.

Konstruktoren für abgeleitete Klassen

Wenn eine Klasse von einer anderen Klasse erbt, können Konstruktoren einen Konstruktor aus der Basisklasse mit dem base Schlüsselwort (keyword) aufrufen. Wenn die abgeleitete Klasse keinen Konstruktor aus der Basisklasse explizit aufruft, ruft sie stattdessen den Standardkonstruktor für die Basisklasse auf.

Um einen nicht standardmäßigen Basiskonstruktor aufzurufen, fügen Sie : base(<parameters>) nach den Konstruktorparametern und vor dem Textkörperblock hinzu.

class <derived-class> : <base-class> {
    <derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
        # initialization code
    }
}

Beim Definieren eines Konstruktors, der einen Basisklassenkonstruktor aufruft, können die Parameter eines der folgenden Elemente sein:

  • Die Variable eines parameters für den abgeleiteten Klassenkonstruktor.
  • Ein beliebiger statischer Wert.
  • Jeder Ausdruck, der zu einem Wert des Parametertyps ausgewertet wird.

Ein Beispiel für Konstruktoren für eine abgeleitete Klasse finden Sie unter Beispiel 5.

Verketten von Konstruktoren

Im Gegensatz zu C# können PowerShell-Klassenkonstruktoren keine Verkettung mit der : this(<parameters>) Syntax verwenden. Um die Codeduplizierung zu reduzieren, verwenden Sie eine ausgeblendete Init() Methode mit mehreren Überladungen zum gleichen Effekt. Beispiel 4 zeigt eine Klasse mit diesem Muster.

Hinzufügen von Instanzeigenschaften und -methoden mit Update-TypeData

Über das direkte Deklarieren von Eigenschaften und Methoden in der Klassendefinition hinaus können Sie Eigenschaften 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 <class-name> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            Name       = '<member-name>'
            MemberType = '<member-type>'
            Value      = <member-definition>
        }
    )

    static <class-name>() {
        $TypeName = [<class-name>].Name
        foreach ($Definition in [<class-name>]::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.

Fügen Sie der Klasse nur Eigenschaften in nicht statischen Konstruktoren hinzu, wenn sie nicht mit Update-TypeDataschreibgeschützten Eigenschaften definiert werden können.

Weitere Informationen zum Definieren von Instanzmethoden mit Update-TypeData, finden Sie unter about_Classes_Methods. Weitere Informationen zum Definieren von Instanzeigenschaften mit Update-TypeData, finden Sie unter about_Classes_Properties.

Begrenzungen

PowerShell-Klassenkonstruktoren haben die folgenden Einschränkungen:

  • Die Konstruktorkette wird nicht implementiert.

    Problemumgehung: Definieren Sie ausgeblendete Init() Methoden, und rufen Sie sie aus den Konstruktoren auf.

  • Konstruktorparameter können keine Attribute verwenden, einschließlich Validierungsattributen.

    Problemumgehung: Weisen Sie die Parameter im Konstruktortext erneut mit dem Überprüfungsattribut zu.

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

    Abhilfen: Keine.

  • Wenn eine Überladung eines Konstruktors ausgeblendet ist, wird jede Überladung für den Konstruktor ebenfalls als ausgeblendet behandelt.

    Abhilfen: Keine.

Weitere Informationen