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:
- 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.
- Usare
Update-TypeData
per definire unScriptMethod
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 conGet-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 eDaysAgo()
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 delToString()
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.