Share via


about_Classes_Methods

Descrizione breve

Descrive come definire i metodi per le classi di PowerShell.

Descrizione lunga

I metodi definiscono le azioni che una classe è in grado di eseguire. I metodi possono accettare parametri che specificano i dati di input. I metodi definiscono sempre un tipo di output. Se un metodo non restituisce alcun output, deve avere il tipo di output Void . Se un metodo non definisce in modo esplicito un tipo di output, il tipo di output del metodo è Void.

Nei metodi di classe non viene inviato alcun oggetto alla pipeline, ad eccezione di quelli specificati nell'istruzione return . Non è presente alcun output accidentale nella pipeline dal codice.

Nota

Questo è fondamentalmente diverso dal modo in cui PowerShell gestisce l'output, dove tutto passa alla pipeline.

Gli errori non determininti scritti nel flusso di errore dall'interno di un metodo di classe non vengono passati attraverso. È necessario utilizzare throw per visualizzare un errore irreversibile. Usando i Write-* cmdlet, è comunque possibile scrivere nei flussi di output di PowerShell dall'interno di un metodo di classe. I cmdlet rispettano le variabili di preferenza nell'ambito chiamante. Tuttavia, è consigliabile evitare di usare i Write-* cmdlet in modo che il metodo restituisca solo oggetti usando l'istruzione return .

I metodi di classe possono fare riferimento all'istanza corrente dell'oggetto classe usando la $this variabile automatica per accedere alle proprietà e ad altri metodi definiti nella classe corrente. La $this variabile automatica non è disponibile nei metodi statici.

I metodi di classe possono avere un numero qualsiasi di attributi, inclusi gli attributi nascosti e statici .

Sintassi

I metodi di classe usano le sintassi seguenti:

Sintassi a una riga

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

Sintassi multilinea

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

Esempi

Esempio 1 - Definizione minima del metodo

Il GetVolume() metodo della classe ExampleCube1 restituisce il volume del cubo. Definisce il tipo di output come numero mobile e restituisce il risultato della moltiplicazione delle proprietà Height, Length e Width dell'istanza.

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

Esempio 2 - Metodo con parametri

Il GeWeight() metodo accetta un input numerico mobile per la densità del cubo e restituisce il peso del cubo, calcolato come volume moltiplicato per densità.

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

Esempio 3 - Metodo senza output

In questo esempio viene definito il Validate() metodo con il tipo di output System.Void. Questo metodo non restituisce alcun output. Se invece la convalida non riesce, viene generato un errore. Il GetVolume() metodo chiama Validate() prima di calcolare il volume del cubo. Se la convalida ha esito negativo, il metodo termina prima del calcolo.

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.

Il metodo genera un'eccezione perché le proprietà Height e Width non sono valide, impedendo alla classe di calcolare il volume corrente.

Esempio 4 - Metodo statico con overload

La classe ExampleCube4 definisce il metodo GetVolume() statico con due overload. Il primo overload include parametri per le dimensioni del cubo e un flag per indicare se il metodo deve convalidare l'input.

Il secondo overload include solo gli input numerici. Chiama il primo overload con $Static come $true. Il secondo overload consente agli utenti di chiamare il metodo senza dover sempre definire se convalidare rigorosamente l'input.

La classe definisce GetVolume() anche come metodo di istanza (non statico). Questo metodo chiama il secondo overload statico, assicurando che il metodo di istanza GetVolume() convalida sempre le dimensioni del cubo prima di restituire il valore di output.

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.

I messaggi dettagliati nelle definizioni dei metodi mostrano come la chiamata iniziale a $this.GetVolume() chiama il metodo statico.

Chiamata diretta del metodo statico con il parametro Strict come $false restituisce 0 per il volume.

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

Firme e overload dei metodi

Ogni metodo di classe ha una firma univoca che definisce come chiamare il metodo . Il tipo di output, il nome e i parametri del metodo definiscono la firma del metodo.

Quando una classe definisce più metodi con lo stesso nome, le definizioni di tale metodo sono overload. Gli overload per un metodo devono avere parametri diversi. Un metodo non può definire due implementazioni con gli stessi parametri, anche se i tipi di output sono diversi.

La classe seguente definisce due metodi, Shuffle() e Deal(). Il Deal() metodo definisce due overload, uno senza parametri e l'altro con il parametro 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() })
    }
}

Output del metodo

Per impostazione predefinita, i metodi non hanno alcun output. Se una firma del metodo include un tipo di output esplicito diverso da Void, il metodo deve restituire un oggetto di tale tipo. I metodi non generano alcun output tranne quando la return parola chiave restituisce in modo esplicito un oggetto.

Parametri del metodo

I metodi di classe possono definire i parametri di input da usare nel corpo del metodo. I parametri del metodo vengono racchiusi tra parentesi e separati da virgole. Le parentesi vuote indicano che il metodo non richiede parametri.

I parametri possono essere definiti su una singola riga o su più righe. I blocchi seguenti mostrano la sintassi per i parametri del metodo.

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

I parametri del metodo possono essere fortemente tipizzato. Se un parametro non è tipizzato, il metodo accetta qualsiasi oggetto per tale parametro. Se il parametro è tipizzato, il metodo tenta di convertire il valore per tale parametro nel tipo corretto, generando un'eccezione se l'input non può essere convertito.

I parametri del metodo non possono definire valori predefiniti. Tutti i parametri del metodo sono obbligatori.

I parametri del metodo non possono avere altri attributi. Ciò impedisce ai metodi di usare i parametri con gli Validate* attributi . Per altre informazioni sugli attributi di convalida, vedere about_Functions_Advanced_Parameters.

È possibile usare uno dei modelli seguenti per aggiungere la convalida ai parametri del metodo:

  1. Riassegnare i parametri alle stesse variabili con gli attributi di convalida necessari. Questa operazione funziona sia per i metodi statici che per i metodi di istanza. Per un esempio di questo modello, vedere Esempio 4.
  2. Usare Update-TypeData per definire un ScriptMethod oggetto che usa gli attributi di convalida direttamente sui parametri. Questa operazione funziona solo per i metodi di istanza. Per altre informazioni, vedere la sezione Definizione dei metodi di istanza con Update-TypeData .

Variabili automatiche nei metodi

Non tutte le variabili automatiche sono disponibili nei metodi. L'elenco seguente include variabili automatiche e suggerimenti per specificare se e come usarli nei metodi della classe PowerShell. Le variabili automatiche non incluse nell'elenco non sono disponibili per i metodi di classe.

  • $? - Accesso normale.
  • $_ - Accesso normale.
  • $args - Usare invece le variabili di parametro esplicite.
  • $ConsoleFileName - Accedere come $Script:ConsoleFileName invece.
  • $Error - Accesso normale.
  • $EnabledExperimentalFeatures - Accedere come $Script:EnabledExperimentalFeatures invece.
  • $Event - Accesso normale.
  • $EventArgs - Accesso normale.
  • $EventSubscriber - Accesso normale.
  • $ExecutionContext - Accedere come $Script:ExecutionContext invece.
  • $false - Accesso normale.
  • $foreach - Accesso normale.
  • $HOME - Accedere come $Script:HOME invece.
  • $Host - Accedere come $Script:Host invece.
  • $input - Usare invece le variabili di parametro esplicite.
  • $IsCoreCLR - Accedere come $Script:IsCoreCLR invece.
  • $IsLinux - Accedere come $Script:IsLinux invece.
  • $IsMacOS - Accedere come $Script:IsMacOS invece.
  • $IsWindows - Accedere come $Script:IsWindows invece.
  • $LASTEXITCODE - Accesso normale.
  • $Matches - Accesso normale.
  • $MyInvocation - Accesso normale.
  • $NestedPromptLevel - Accesso normale.
  • $null - Accesso normale.
  • $PID - Accedere come $Script:PID invece.
  • $PROFILE - Accedere come $Script:PROFILE invece.
  • $PSBoundParameters - Non usare questa variabile. È destinato a cmdlet e funzioni. L'uso in una classe può avere effetti collaterali imprevisti.
  • $PSCmdlet - Non usare questa variabile. È destinato a cmdlet e funzioni. L'uso in una classe può avere effetti collaterali imprevisti.
  • $PSCommandPath - Accesso normale.
  • $PSCulture - Accedere come $Script:PSCulture invece.
  • $PSEdition - Accedere come $Script:PSEdition invece.
  • $PSHOME - Accedere come $Script:PSHOME invece.
  • $PSItem - Accesso normale.
  • $PSScriptRoot - Accesso normale.
  • $PSSenderInfo - Accedere come $Script:PSSenderInfo invece.
  • $PSUICulture - Accedere come $Script:PSUICulture invece.
  • $PSVersionTable - Accedere come $Script:PSVersionTable invece.
  • $PWD - Accesso normale.
  • $Sender - Accesso normale.
  • $ShellId - Accedere come $Script:ShellId invece.
  • $StackTrace - Accesso normale.
  • $switch - Accesso normale.
  • $this - Accesso normale. In un metodo di classe è $this sempre l'istanza corrente della classe . È possibile accedere alle proprietà e ai metodi della classe. Non è disponibile nei metodi statici.
  • $true - Accesso normale.

Per altre informazioni sulle variabili automatiche, vedere about_Automatic_Variables.

Metodi nascosti

È possibile nascondere i metodi di una classe dichiarandoli con la hidden parola chiave . I metodi di classe nascosti sono:

  • Non incluso nell'elenco dei membri della classe restituiti dal Get-Member cmdlet . Per visualizzare i metodi nascosti con Get-Member, usare il parametro Force .
  • Non visualizzato in completamento tramite tabulazione o IntelliSense, a meno che il completamento non si verifichi nella classe che definisce il metodo nascosto.
  • Membri pubblici della classe . Possono essere chiamati e ereditati. Nascondere un metodo non lo rende privato. Nasconde solo il metodo come descritto nei punti precedenti.

Nota

Quando si nasconde qualsiasi overload per un metodo, tale metodo viene rimosso da IntelliSense, i risultati di completamento e l'output predefinito per Get-Member.

Per altre informazioni sulla hidden parola chiave, vedere about_Hidden.

Metodi statici

È possibile definire un metodo come appartenente alla classe stessa anziché alle istanze della classe dichiarando il metodo con la static parola chiave . Metodi di classe statici:

  • Sono sempre disponibili, indipendentemente dalla creazione di istanze della classe.
  • Vengono condivisi tra tutte le istanze della classe .
  • Sono sempre disponibili.
  • Non è possibile accedere alle proprietà dell'istanza della classe . Possono accedere solo alle proprietà statiche.
  • Live per l'intero intervallo di sessione.

Metodi della classe derivata

Quando una classe deriva da una classe di base, eredita i metodi della classe di base e i relativi overload. Tutti gli overload di metodo definiti nella classe base, inclusi i metodi nascosti, sono disponibili nella classe derivata.

Una classe derivata può eseguire l'override di un overload di metodo ereditato ridefinendolo nella definizione della classe. Per eseguire l'override dell'overload, i tipi di parametro devono essere uguali a quello della classe base. Il tipo di output per l'overload può essere diverso.

A differenza dei costruttori, i metodi non possono usare la : base(<parameters>) sintassi per richiamare un overload della classe di base per il metodo . L'overload ridefinito nella classe derivata sostituisce completamente l'overload definito dalla classe base.

Nell'esempio seguente viene illustrato il comportamento per i metodi statici e di istanza nelle classi derivate.

La classe base definisce:

  • Metodi statici Now() per restituire l'ora corrente e DaysAgo() per restituire una data nel passato.
  • La proprietà dell'istanza TimeStamp e un ToString() metodo di istanza che restituisce la rappresentazione di stringa di tale proprietà. In questo modo, quando un'istanza viene usata in una stringa, viene convertita nella stringa datetime anziché nel nome della classe.
  • Metodo di istanza SetTimeStamp() con due overload. Quando il metodo viene chiamato senza parametri, imposta timestamp sull'ora corrente. Quando il metodo viene chiamato con un valore DateTime, imposta timestamp su tale valore.
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()
    }
}

Il blocco successivo definisce le classi derivate da BaseClass:

  • DerivedClassA eredita da BaseClass senza override.
  • DerivedClassB esegue l'override del DaysAgo() metodo statico per restituire una rappresentazione di stringa anziché l'oggetto DateTime . Esegue anche l'override del ToString() metodo di istanza per restituire il timestamp come stringa di data ISO8601.
  • DerivedClassC esegue l'override dell'overload senza parametri del SetTimeStamp() metodo in modo che l'impostazione del timestamp senza parametri imposti la data su 10 giorni prima della data corrente.
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))
    }
}

Il blocco seguente mostra l'output del metodo statico Now() per le classi definite. L'output è lo stesso per ogni classe, perché le classi derivate non eseguono l'override dell'implementazione della classe base del metodo .

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

Il blocco successivo chiama il DaysAgo() metodo statico di ogni classe. Solo l'output per DerivedClassB è diverso, perché esegue l'overrode dell'implementazione di base.

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

Il blocco seguente illustra la presentazione di una nuova istanza di una nuova istanza per ogni classe. La rappresentazione per DerivedClassB è diversa perché esegue l'overrode del metodo di ToString() istanza.

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

Il blocco successivo chiama il SetTimeStamp() metodo di istanza per ogni istanza, impostando la proprietà TimeStamp su una data specifica. Ogni istanza ha la stessa data, perché nessuna delle classi derivate esegue l'override dell'overload con parametri per il metodo .

[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

L'ultimo blocco chiama SetTimeStamp() senza parametri. L'output mostra che il valore per l'istanza DerivedClassC è impostato su 10 giorni prima degli altri.

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

Definizione di metodi di istanza con Update-TypeData

Oltre a dichiarare i metodi direttamente nella definizione della classe, è possibile definire metodi per le istanze di una classe nel costruttore statico usando il Update-TypeData cmdlet .

Usare questo frammento di codice come punto di partenza per il modello. Sostituire il testo segnaposto tra parentesi angolari in base alle esigenze.

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

Suggerimento

Il Add-Member cmdlet può aggiungere proprietà e metodi a una classe in costruttori non statici, ma il cmdlet viene eseguito ogni volta che viene chiamato il costruttore. L'uso Update-TypeData nel costruttore statico garantisce che il codice per l'aggiunta dei membri alla classe debba essere eseguito una sola volta in una sessione.

Definizione di metodi con valori di parametro predefiniti e attributi di convalida

I metodi definiti direttamente in una dichiarazione di classe non possono definire valori predefiniti o attributi di convalida nei parametri del metodo. Per definire metodi di classe con valori predefiniti o attributi di convalida, è necessario definirli come membri ScriptMethod .

In questo esempio, la classe CardDeck definisce un Draw() metodo che usa sia un attributo di convalida che un valore predefinito per il parametro 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.

Nota

Anche se questo modello funziona per gli attributi di convalida, si noti che l'eccezione è fuorviante, facendo riferimento a un'impossibilità di aggiungere un attributo. Potrebbe trattarsi di un'esperienza utente migliore per controllare in modo esplicito il valore del parametro e generare invece un errore significativo. In questo modo, gli utenti possono capire perché vengono visualizzati l'errore e cosa fare.

Limiti

I metodi della classe PowerShell presentano le limitazioni seguenti:

  • I parametri del metodo non possono usare attributi, inclusi gli attributi di convalida.

    Soluzione alternativa: riassegnare i parametri nel corpo del metodo con l'attributo di convalida o definire il metodo nel costruttore statico con il Update-TypeData cmdlet .

  • I parametri del metodo non possono definire valori predefiniti. I parametri sono sempre obbligatori.

    Soluzione alternativa: definire il metodo nel costruttore statico con il Update-TypeData cmdlet .

  • I metodi sono sempre pubblici, anche quando sono nascosti. Possono essere sottoposti a override quando la classe viene ereditata.

    Soluzione alternativa: nessuna.

  • Se un overload di un metodo è nascosto, ogni overload per tale metodo viene considerato anche nascosto.

    Soluzione alternativa: nessuna.

Vedi anche