Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Breve descrizione
Descrive come definire i metodi per le classi di PowerShell.
Descrizione lunga
I metodi definiscono le azioni che una classe può 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 cmdlet Write-*, è 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 cmdlet Write-* 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 utilizzando la variabile automatica $this 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 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 metodo GetVolume() 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, Lengthe 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 metodo GeWeight() 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
Questo esempio definisce il metodo Validate() con il tipo di output come System.Void. Questo metodo non restituisce alcun output. Se invece la convalida non riesce, viene generato un errore. Il metodo GetVolume() 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 statico GetVolume() 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 $Strict come $true. Il secondo overload consente agli utenti di chiamare il metodo senza dover sempre definire se convalidare rigorosamente l'input.
La classe definisce anche GetVolume() come metodo di istanza (non statico). Questo metodo chiama il secondo overload statico, assicurando che l'istanza GetVolume() metodo 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.
Chiamando il metodo statico direttamente 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 vengono 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 metodo Deal() 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 parola chiave return 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 sono racchiusi tra parentesi e sono 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. In questo modo, i metodi non usano parametri con gli attributi Validate*. 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-TypeDataper definire unScriptMethodche usa direttamente gli attributi di convalida nei 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: accesso come$Script:ConsoleFileName. -
$Error: accesso normale. -
$EnabledExperimentalFeatures: accesso come$Script:EnabledExperimentalFeatures. -
$Event: accesso normale. -
$EventArgs: accesso normale. -
$EventSubscriber: accesso normale. -
$ExecutionContext: accesso come$Script:ExecutionContext. -
$false: accesso normale. -
$foreach: accesso normale. -
$HOME: accesso come$Script:HOME. -
$Host: accesso come$Script:Host. -
$input: usare invece le variabili di parametro esplicite. -
$IsCoreCLR: accesso come$Script:IsCoreCLR. -
$IsLinux: accesso come$Script:IsLinux. -
$IsMacOS: accesso come$Script:IsMacOS. -
$IsWindows: accesso come$Script:IsWindows. -
$LASTEXITCODE: accesso normale. -
$Matches: accesso normale. -
$MyInvocation: accesso normale. -
$NestedPromptLevel: accesso normale. -
$null: accesso normale. -
$PID: accesso come$Script:PID. -
$PROFILE: accesso come$Script:PROFILE. -
$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: accesso come$Script:PSCulture. -
$PSEdition: accesso come$Script:PSEdition. -
$PSHOME: accesso come$Script:PSHOME. -
$PSItem: accesso normale. -
$PSScriptRoot: accesso normale. -
$PSSenderInfo: accesso come$Script:PSSenderInfo. -
$PSUICulture: accesso come$Script:PSUICulture. -
$PSVersionTable: accesso come$Script:PSVersionTable. -
$PWD: accesso normale. -
$Sender: accesso normale. -
$ShellId: accesso come$Script:ShellId. -
$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 parola chiave hidden.
I metodi di classe nascosti sono:
- Non incluso nell'elenco dei membri della classe restituiti dal cmdlet
Get-Member. 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 parola chiave hidden, vedere about_Hidden.
Metodi statici
È possibile definire un metodo come appartenente alla classe stessa anziché alle istanze della classe dichiarando il metodo con la parola chiave static. 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 sintassi : base(<parameters>) 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:
- I metodi statici
Now()per restituire l'ora corrente eDaysAgo()per restituire una data nel passato. - La proprietà dell'istanza timestamp e un metodo di istanza
ToString()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. - Il metodo di istanza
SetTimeStamp()con due overload. Quando il metodo viene chiamato senza parametri, imposta l'TimeStamp sull'ora corrente. Quando il metodo viene chiamato con un DateTime, imposta il 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 metodo statico
DaysAgo()per restituire una rappresentazione di stringa anziché l'oggetto DateTime. Esegue anche l'override del metodo di istanzaToString()per restituire il timestamp come stringa di data ISO8601. -
DerivedClassC esegue l'override dell'overload senza parametri del metodo
SetTimeStamp()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 Now() statico 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 metodo statico DaysAgo() di ogni classe. Solo l'output per DerivedClassB è diverso, perché sovrascrivo l'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 istanza ToString().
"`$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 metodo di istanza SetTimeStamp() 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 di 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
Definire 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 cmdlet Update-TypeData.
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
}
}
}
Mancia
Il cmdlet Add-Member 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 di 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 i metodi di classe con valori predefiniti o attributi di convalida, è necessario definirli come membri di ScriptMethod.
In questo esempio, la classe CardDeck definisce un metodo Draw() 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.
Limitazioni
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 cmdlet
Update-TypeData.I parametri del metodo non possono definire valori predefiniti. I parametri sono sempre obbligatori.
Soluzione alternativa: definire il metodo nel costruttore statico con il cmdlet
Update-TypeData.I metodi sono sempre pubblici, anche quando sono nascosti. Possono essere sottoposti a override quando la classe viene ereditata.
Soluzione alternativa: Nessuno.
Se un overload di un metodo è nascosto, ogni overload per tale metodo viene considerato anche nascosto.
Soluzione alternativa: Nessuno.