about_Classes_Methods

Descripción breve

Describe cómo definir métodos para las clases de PowerShell.

Descripción larga

Los métodos definen las acciones que una clase puede realizar. Los métodos pueden tomar parámetros que especifican datos de entrada. Los métodos siempre definen un tipo de salida. Si un método no devuelve ninguna salida, debe tener el tipo de salida Void . Si un método no define explícitamente un tipo de salida, el tipo de salida del método es Void.

En los métodos de clase, no se envía ningún objeto a la canalización excepto los especificados en la return instrucción . No hay ninguna salida accidental en la canalización desde el código.

Nota:

Esto es fundamentalmente diferente de cómo las funciones de PowerShell controlan la salida, donde todo va a la canalización.

Los errores no predeterminados escritos en la secuencia de errores desde dentro de un método de clase no se pasan a través. Debe usar throw para exponer un error de terminación. Con los cmdlets, todavía puede escribir en los Write-* flujos de salida de PowerShell desde dentro de un método de clase. Los cmdlets respetan las variables de preferencia en el ámbito de llamada. Sin embargo, debe evitar usar los Write-* cmdlets para que el método solo genera objetos mediante la return instrucción .

Los métodos de clase pueden hacer referencia a la instancia actual del objeto de clase mediante la $this variable automática para tener acceso a propiedades y otros métodos definidos en la clase actual. La $this variable automática no está disponible en métodos estáticos.

Los métodos de clase pueden tener cualquier número de atributos, incluidos los atributos ocultos y estáticos .

Sintaxis

Los métodos de clase usan las sintaxis siguientes:

Sintaxis de una línea

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

Sintaxis multilínea

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

Ejemplos

Ejemplo 1: definición de método mínima

El GetVolume() método de la clase ExampleCube1 devuelve el volumen del cubo. Define el tipo de salida como un número flotante y devuelve el resultado de multiplicar las propiedades Height, Length y Width de la instancia.

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

Ejemplo 2: método con parámetros

El GeWeight() método toma una entrada de número flotante para la densidad del cubo y devuelve el peso del cubo, calculado como volumen multiplicado por densidad.

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

Ejemplo 3: método sin salida

En este ejemplo se define el Validate() método con el tipo de salida como System.Void. Este método no devuelve ninguna salida. En su lugar, si se produce un error en la validación, se produce un error. El GetVolume() método llama a Validate() antes de calcular el volumen del cubo. Si se produce un error en la validación, el método finaliza antes del cálculo.

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.

El método produce una excepción porque las propiedades Height y Width no son válidas, lo que impide que la clase calcule el volumen actual.

Ejemplo 4: Método estático con sobrecargas

La clase ExampleCube4 define el método GetVolume() estático con dos sobrecargas. La primera sobrecarga tiene parámetros para las dimensiones del cubo y una marca para indicar si el método debe validar la entrada.

La segunda sobrecarga solo incluye las entradas numéricas. Llama a la primera sobrecarga con $Static como $true. La segunda sobrecarga proporciona a los usuarios una manera de llamar al método sin tener que definir siempre si se debe validar estrictamente la entrada.

La clase también define GetVolume() como un método de instancia (no estático). Este método llama a la segunda sobrecarga estática, asegurándose de que el método de instancia GetVolume() valida siempre las dimensiones del cubo antes de devolver el valor de salida.

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.

Los mensajes detallados de las definiciones de método muestran cómo la llamada inicial a llama al $this.GetVolume() método estático.

Llamar al método estático directamente con el parámetro Strict como $false devuelve 0 para el volumen.

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

Firmas y sobrecargas del método

Cada método de clase tiene una firma única que define cómo llamar al método . El tipo de salida, el nombre y los parámetros del método definen la firma del método.

Cuando una clase define más de un método con el mismo nombre, las definiciones de ese método son sobrecargas. Las sobrecargas de un método deben tener parámetros diferentes. Un método no puede definir dos implementaciones con los mismos parámetros, incluso si los tipos de salida son diferentes.

La siguiente clase define dos métodos y Shuffle() Deal(). El Deal() método define dos sobrecargas, una sin parámetros y la otra con el parámetro 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() })
    }
}

Salida del método

De forma predeterminada, los métodos no tienen ninguna salida. Si una firma de método incluye un tipo de salida explícito distinto de Void, el método debe devolver un objeto de ese tipo. Los métodos no emiten ninguna salida excepto cuando la return palabra clave devuelve explícitamente un objeto .

Parámetros de métodos

Los métodos de clase pueden definir parámetros de entrada que se usarán en el cuerpo del método. Los parámetros de método se encierran entre paréntesis y se separan por comas. Los paréntesis vacíos indican que el método no requiere parámetros.

Los parámetros se pueden definir en una sola línea o en varias líneas. Los siguientes bloques muestran la sintaxis de los parámetros del método.

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

Los parámetros de método se pueden escribir fuertemente. Si un parámetro no está escrito, el método acepta cualquier objeto para ese parámetro. Si el parámetro está escrito, el método intenta convertir el valor de ese parámetro en el tipo correcto, iniciando una excepción si no se puede convertir la entrada.

Los parámetros del método no pueden definir valores predeterminados. Todos los parámetros de método son obligatorios.

Los parámetros de método no pueden tener ningún otro atributo. Esto impide que los métodos usen parámetros con los Validate* atributos . Para obtener más información sobre los atributos de validación, consulte about_Functions_Advanced_Parameters.

Puede usar uno de los siguientes patrones para agregar validación a los parámetros del método:

  1. Reasigna los parámetros a las mismas variables con los atributos de validación necesarios. Esto funciona tanto para métodos estáticos como para instancias. Para obtener un ejemplo de este patrón, vea Ejemplo 4.
  2. Use Update-TypeData para definir un ScriptMethod que use atributos de validación en los parámetros directamente. Esto solo funciona para los métodos de instancia. Para obtener más información, consulte la sección Definición de métodos de instancia con Update-TypeData .

Variables automáticas en métodos

No todas las variables automáticas están disponibles en métodos. En la lista siguiente se incluyen variables automáticas y sugerencias sobre si y cómo usarlas en métodos de clase de PowerShell. Las variables automáticas no incluidas en la lista no están disponibles para los métodos de clase.

  • $? - Acceso como normal.
  • $_ - Acceso como normal.
  • $args : use las variables de parámetro explícitas en su lugar.
  • $ConsoleFileName - Acceso como $Script:ConsoleFileName en su lugar.
  • $Error - Acceso como normal.
  • $EnabledExperimentalFeatures - Acceso como $Script:EnabledExperimentalFeatures en su lugar.
  • $Event - Acceso como normal.
  • $EventArgs - Acceso como normal.
  • $EventSubscriber - Acceso como normal.
  • $ExecutionContext - Acceso como $Script:ExecutionContext en su lugar.
  • $false - Acceso como normal.
  • $foreach - Acceso como normal.
  • $HOME - Acceso como $Script:HOME en su lugar.
  • $Host - Acceso como $Script:Host en su lugar.
  • $input : use las variables de parámetro explícitas en su lugar.
  • $IsCoreCLR - Acceso como $Script:IsCoreCLR en su lugar.
  • $IsLinux - Acceso como $Script:IsLinux en su lugar.
  • $IsMacOS - Acceso como $Script:IsMacOS en su lugar.
  • $IsWindows - Acceso como $Script:IsWindows en su lugar.
  • $LASTEXITCODE - Acceso como normal.
  • $Matches - Acceso como normal.
  • $MyInvocation - Acceso como normal.
  • $NestedPromptLevel - Acceso como normal.
  • $null - Acceso como normal.
  • $PID - Acceso como $Script:PID en su lugar.
  • $PROFILE - Acceso como $Script:PROFILE en su lugar.
  • $PSBoundParameters - No use esta variable. Está diseñado para cmdlets y funciones. Usarlo en una clase puede tener efectos secundarios inesperados.
  • $PSCmdlet - No use esta variable. Está diseñado para cmdlets y funciones. Usarlo en una clase puede tener efectos secundarios inesperados.
  • $PSCommandPath - Acceso como normal.
  • $PSCulture - Acceso como $Script:PSCulture en su lugar.
  • $PSEdition - Acceso como $Script:PSEdition en su lugar.
  • $PSHOME - Acceso como $Script:PSHOME en su lugar.
  • $PSItem - Acceso como normal.
  • $PSScriptRoot - Acceso como normal.
  • $PSSenderInfo - Acceso como $Script:PSSenderInfo en su lugar.
  • $PSUICulture - Acceso como $Script:PSUICulture en su lugar.
  • $PSVersionTable - Acceso como $Script:PSVersionTable en su lugar.
  • $PWD - Acceso como normal.
  • $Sender - Acceso como normal.
  • $ShellId - Acceso como $Script:ShellId en su lugar.
  • $StackTrace - Acceso como normal.
  • $switch - Acceso como normal.
  • $this - Acceso como normal. En un método de clase, $this siempre es la instancia actual de la clase . Puede acceder a las propiedades y métodos de clase con él. No está disponible en métodos estáticos.
  • $true - Acceso como normal.

Para obtener más información sobre las variables automáticas, consulte about_Automatic_Variables.

Métodos ocultos

Puede ocultar métodos de una clase declarandolos con la hidden palabra clave . Los métodos de clase ocultos son:

  • No se incluye en la lista de miembros de clase devueltos por el Get-Member cmdlet . Para mostrar métodos ocultos con Get-Member, use el parámetro Force .
  • No se muestra en la finalización de tabulación o IntelliSense a menos que se produzca la finalización en la clase que define el método oculto.
  • Miembros públicos de la clase . Se pueden llamar y heredar. Ocultar un método no lo hace privado. Solo oculta el método como se describe en los puntos anteriores.

Nota:

Al ocultar cualquier sobrecarga de un método, ese método se quita de IntelliSense, los resultados de finalización y la salida predeterminada para Get-Member.

Para obtener más información sobre la hidden palabra clave , consulte about_Hidden.

Métodos estáticos

Puede definir un método como perteneciente a la propia clase en lugar de las instancias de la clase declarando el método con la static palabra clave . Métodos de clase estáticos:

  • Siempre están disponibles, independientemente de la creación de instancias de clase.
  • Se comparten en todas las instancias de la clase .
  • Siempre están disponibles.
  • No se puede acceder a las propiedades de instancia de la clase . Solo pueden acceder a propiedades estáticas.
  • Live para todo el intervalo de sesión.

Métodos de clase derivados

Cuando una clase se deriva de una clase base, hereda los métodos de la clase base y sus sobrecargas. Las sobrecargas de método definidas en la clase base, incluidos los métodos ocultos, están disponibles en la clase derivada.

Una clase derivada puede invalidar una sobrecarga de método heredado redefinirla en la definición de clase. Para invalidar la sobrecarga, los tipos de parámetro deben ser los mismos que para la clase base. El tipo de salida de la sobrecarga puede ser diferente.

A diferencia de los constructores, los métodos no pueden usar la : base(<parameters>) sintaxis para invocar una sobrecarga de clase base para el método . La sobrecarga redefinida de la clase derivada reemplaza completamente la sobrecarga definida por la clase base.

En el ejemplo siguiente se muestra el comportamiento de los métodos estáticos y de instancia en las clases derivadas.

La clase base define:

  • Los métodos estáticos Now() para devolver la hora actual y DaysAgo() para devolver una fecha en el pasado.
  • La propiedad de instancia TimeStamp y un ToString() método de instancia que devuelve la representación de cadena de esa propiedad. Esto garantiza que, cuando se usa una instancia en una cadena, se convierte en la cadena datetime en lugar del nombre de clase.
  • Método de instancia SetTimeStamp() con dos sobrecargas. Cuando se llama al método sin parámetros, establece timeStamp en la hora actual. Cuando se llama al método con dateTime, establece timeStamp en ese valor.
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()
    }
}

El siguiente bloque define las clases derivadas de BaseClass:

  • DerivedClassA hereda de BaseClass sin invalidaciones.
  • DerivedClassB invalida el DaysAgo() método estático para devolver una representación de cadena en lugar del objeto DateTime . También invalida el ToString() método de instancia para devolver la marca de tiempo como una cadena de fecha ISO8601.
  • DerivedClassC invalida la sobrecarga sin parámetros del SetTimeStamp() método para que establecer la marca de tiempo sin parámetros establezca la fecha en 10 días antes de la fecha actual.
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))
    }
}

En el bloque siguiente se muestra la salida del método estático Now() para las clases definidas. La salida es la misma para cada clase, ya que las clases derivadas no invalidan la implementación de clase base del método .

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

El siguiente bloque llama al DaysAgo() método estático de cada clase. Solo la salida de DerivedClassB es diferente, ya que sobrepone la implementación 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

En el bloque siguiente se muestra la presentación de cadena de una nueva instancia para cada clase. La representación de DerivedClassB es diferente porque sobrepone el ToString() método de instancia.

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

El siguiente bloque llama al SetTimeStamp() método de instancia para cada instancia, estableciendo la propiedad TimeStamp en una fecha específica. Cada instancia tiene la misma fecha, ya que ninguna de las clases derivadas invalida la sobrecarga parametrizada para el método .

[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

El último bloque llama SetTimeStamp() sin parámetros. La salida muestra que el valor de la instancia de DerivedClassC se establece en 10 días antes de los demás.

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

Definición de métodos de instancia con Update-TypeData

Más allá de declarar métodos directamente en la definición de clase, puede definir métodos para instancias de una clase en el constructor estático mediante el Update-TypeData cmdlet .

Use este fragmento de código como punto de partida para el patrón. Reemplace el texto del marcador de posición entre corchetes angulares según sea necesario.

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

Sugerencia

El Add-Member cmdlet puede agregar propiedades y métodos a una clase en constructores no estáticos, pero el cmdlet se ejecuta cada vez que se llama al constructor. El uso Update-TypeData de en el constructor estático garantiza que el código para agregar los miembros a la clase solo debe ejecutarse una vez en una sesión.

Definición de métodos con valores de parámetro predeterminados y atributos de validación

Los métodos definidos directamente en una declaración de clase no pueden definir valores predeterminados ni atributos de validación en los parámetros del método. Para definir métodos de clase con valores predeterminados o atributos de validación, deben definirse como miembros ScriptMethod .

En este ejemplo, la clase CardDeck define un Draw() método que usa un atributo de validación y un valor predeterminado para el parámetro 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:

Aunque este patrón funciona para los atributos de validación, observe que la excepción es engañosa, haciendo referencia a una incapacidad para agregar un atributo. Puede ser una mejor experiencia de usuario para comprobar explícitamente el valor del parámetro y generar un error significativo en su lugar. De este modo, los usuarios pueden comprender por qué ven el error y qué hacer sobre él.

Limitaciones

Los métodos de clase de PowerShell tienen las siguientes limitaciones:

  • Los parámetros de método no pueden usar ningún atributo, incluidos los atributos de validación.

    Solución alternativa: vuelva a asignar los parámetros en el cuerpo del método con el atributo de validación o defina el método en el constructor estático con el Update-TypeData cmdlet .

  • Los parámetros del método no pueden definir valores predeterminados. Los parámetros siempre son obligatorios.

    Solución alternativa: defina el método en el constructor estático con el Update-TypeData cmdlet .

  • Los métodos siempre son públicos, incluso cuando están ocultos. Se pueden invalidar cuando se hereda la clase .

    Solución alternativa: Ninguna.

  • Si alguna sobrecarga de un método está oculta, todas las sobrecargas de ese método también se tratan como ocultas.

    Solución alternativa: Ninguna.

Consulte también