about_Classes_Methods

簡単な説明

PowerShell クラスのメソッドを定義する方法について説明します。

詳細な説明

メソッドは、クラスが実行できるアクションを定義します。 メソッドは、入力データを指定するパラメーターを受け取ることができます。 メソッドは常に出力の種類を定義します。 メソッドが出力を返さない場合は、Void 出力型が必要です。 メソッドが出力型を明示的に定義しない場合、メソッドの出力型は Void です

クラス メソッドでは、ステートメントで指定されているものを除き、オブジェクトはパイプラインに return 送信されません。 コードからパイプラインに誤って出力されることはありません。

Note

これは、PowerShell 関数が出力を処理する方法とは根本的に異なり、すべてがパイプラインに送信されます。

クラス メソッド内からエラー ストリームに書き込まれた非終了エラーは渡されません。 終了エラーを表示するために使用 throw する必要があります。 コマンドレットを Write-* 使用しても、クラス メソッド内から PowerShell の出力ストリームに書き込むことができます。 コマンドレットは、呼び出し元の スコープ内の基本設定変数 を考慮します。 ただし、メソッドがステートメントを Write-* 使用してオブジェクトのみを出力するように、コマンドレットの使用は return 避ける必要があります。

クラス メソッドは、自動変数を使用して $this 、現在のクラスで定義されているプロパティやその他のメソッドにアクセスすることで、クラス オブジェクトの現在のインスタンスを参照できます。 自動変数は $this 静的メソッドでは使用できません。

クラス メソッドには、非表示属性や静的属性など、任意の数の属性を含めることができます。

構文

クラス メソッドでは、次の構文を使用します。

1 行構文

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

複数行の構文

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

例 1 - 最小限のメソッド定義

ExampleCube1 クラスのメソッドはGetVolume()、キューブのボリュームを返します。 出力の種類を浮動小数点数として定義し、インスタンスの Height、LengthWidthプロパティを乗算した結果を返します。

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

例 2 - パラメーターを持つメソッド

このメソッドは GeWeight() 、キューブの密度に対する浮動小数点数入力を受け取り、体積に密度を乗算して計算されたキューブの重みを返します。

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

例 3 - 出力なしのメソッド

この例では、出力の種類が Validate() System.Void であるメソッドを定義します。 このメソッドは出力を返しません。 代わりに、検証が失敗すると、エラーがスローされます。 キューブの GetVolume() ボリュームを計算する前にメソッドが呼び出 Validate() されます。 検証が失敗した場合、メソッドは計算の前に終了します。

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

Invalid cube properties ('Height', 'Width'): Cube dimensions must all be
positive numbers.
At C:\code\classes.examples.ps1:26 char:13
+             throw $Message
+             ~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Invalid cube pr...sitive
    numbers.:String) [], RuntimeException
    + FullyQualifiedErrorId : Invalid cube properties ('Height', 'Width')
   : Cube dimensions must all be positive numbers.

Height プロパティと Width プロパティが無効であり、クラスが現在のボリュームを計算できないため、メソッドは例外をスローします。

例 4 - オーバーロードを含む静的メソッド

ExampleCube4 クラスは、2 つのオーバーロードを持つ静的メソッドGetVolume()を定義します。 最初のオーバーロードには、キューブのディメンションのパラメーターと、メソッドが入力を検証する必要があるかどうかを示すフラグがあります。

2 番目のオーバーロードには、数値入力のみが含まれます。 as で最初のオーバーロードを$Static$true呼び出します。 2 番目のオーバーロードは、入力を厳密に検証するかどうかを常に定義しなくても、メソッドを呼び出す方法をユーザーに提供します。

このクラスは、インスタンス (非静的) メソッドとしても定義されます GetVolume() 。 このメソッドは 2 番目の静的オーバーロードを呼び出し、出力値を返す前にインスタンス GetVolume() メソッドが常にキューブのディメンションを検証することを保証します。

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)

The variable cannot be validated because the value 0 is not a valid value
for the Width variable.
At C:\code\classes.examples.ps1:19 char:13
+             [ValidateScript({$_ -gt 0 })]$Width  = $Width
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataEx
   ception
    + FullyQualifiedErrorId : ValidateSetFailure

メソッド定義の詳細メッセージは、静的メソッドを呼び出す最初の呼び出しの方法を $this.GetVolume() 示しています。

ボリュームの戻り値として $false Strict パラメーターを使用して静的メソッドを0直接呼び出します。

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

メソッドシグネチャとオーバーロード

すべてのクラス メソッドには、メソッドの呼び出し方法を定義する一意のシグネチャがあります。 メソッドの出力の型、名前、およびパラメーターによって、メソッドシグネチャが定義されます。

クラスで同じ名前のメソッドが複数定義されている場合、そのメソッドの定義はオーバーロードになります。 メソッドのオーバーロードには、異なるパラメーターが必要です。 メソッドは、出力の種類が異なる場合でも、同じパラメーターを持つ 2 つの実装を定義することはできません。

次のクラスでは、2 つのメソッドと Deal(). Shuffle() メソッドは Deal() 2 つのオーバーロードを定義します。1 つはパラメーターを持たず、もう 1 つは 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() })
    }
}

メソッドの出力

既定では、メソッドには出力がありません。 メソッド シグネチャに Void 以外の明示的な出力型が含まれている場合、メソッドはその型のオブジェクトを返す必要があります。 メソッドは、キーワード (keyword)がオブジェクトを明示的に返す場合をreturn除き、出力を出力しません。

メソッド parameters

クラス メソッドは、メソッド本体で使用する入力パラメーターを定義できます。 メソッド パラメーターはかっこで囲み、各パラメーターをコンマで区切ります。 かっこ内を空にすると、メソッドでパラメーターが不要なことを意味します。

パラメーターは、1 行または複数行で定義できます。 次のブロックは、メソッド パラメーターの構文を示しています。

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

メソッド パラメーターは厳密に型指定できます。 パラメーターが型指定されていない場合、メソッドはそのパラメーターのオブジェクトを受け入れます。 パラメーターが型指定されている場合、メソッドはそのパラメーターの値を正しい型に変換しようとします。入力を変換できない場合は例外がスローされます。

メソッド パラメーターでは既定値を定義できません。 すべてのメソッド パラメーターは必須です。

メソッド パラメーターに他の属性を指定することはできません。 これにより、メソッドが属性と共にパラメーターを Validate* 使用できなくなります。 検証属性の詳細については、about_Functions_Advanced_Parametersを参照してください

次のいずれかのパターンを使用して、メソッド パラメーターに検証を追加できます。

  1. 必要な検証属性を使用して、パラメーターを同じ変数に再割り当てします。 これは、静的メソッドとインスタンス メソッドの両方で機能します。 このパターンの例については、例 4 を参照してください
  2. パラメーターに対して検証属性を直接使用する a を定義ScriptMethodするために使用Update-TypeDataします。 これはインスタンス メソッドに対してのみ機能します。 詳細については、「Update-TypeData を使用したインスタンス メソッドの定義」セクションを参照してください

メソッド内の自動変数

すべての自動変数がメソッドで使用できるわけではありません。 次の一覧には、自動変数と、PowerShell クラス メソッドで変数を使用するかどうかとその使用方法に関する推奨事項が含まれています。 リストに含まれていない自動変数は、クラス メソッドでは使用できません。

  • $? - 通常どおりアクセスします。
  • $_ - 通常どおりアクセスします。
  • $args - 代わりに明示的なパラメーター変数を使用してください。
  • $ConsoleFileName - 代わりにアクセス $Script:ConsoleFileName します。
  • $Error - 通常どおりアクセスします。
  • $Event - 通常どおりアクセスします。
  • $EventArgs - 通常どおりアクセスします。
  • $EventSubscriber - 通常どおりアクセスします。
  • $ExecutionContext - 代わりにアクセス $Script:ExecutionContext します。
  • $false - 通常どおりアクセスします。
  • $foreach - 通常どおりアクセスします。
  • $HOME - 代わりにアクセス $Script:HOME します。
  • $Host - 代わりにアクセス $Script:Host します。
  • $input - 代わりに明示的なパラメーター変数を使用してください。
  • $LASTEXITCODE - 通常どおりアクセスします。
  • $Matches - 通常どおりアクセスします。
  • $MyInvocation - 通常どおりアクセスします。
  • $NestedPromptLevel - 通常どおりアクセスします。
  • $null - 通常どおりアクセスします。
  • $PID - 代わりにアクセス $Script:PID します。
  • $PROFILE - 代わりにアクセス $Script:PROFILE します。
  • $PSBoundParameters - この変数は使用しないでください。 コマンドレットと関数を対象としています。 クラスで使用すると、予期しない副作用が発生する可能性があります。
  • $PSCmdlet - この変数は使用しないでください。 コマンドレットと関数を対象としています。 クラスで使用すると、予期しない副作用が発生する可能性があります。
  • $PSCommandPath - 通常どおりアクセスします。
  • $PSCulture - 代わりにアクセス $Script:PSCulture します。
  • $PSEdition - 代わりにアクセス $Script:PSEdition します。
  • $PSHOME - 代わりにアクセス $Script:PSHOME します。
  • $PSItem - 通常どおりアクセスします。
  • $PSScriptRoot - 通常どおりアクセスします。
  • $PSSenderInfo - 代わりにアクセス $Script:PSSenderInfo します。
  • $PSUICulture - 代わりにアクセス $Script:PSUICulture します。
  • $PSVersionTable - 代わりにアクセス $Script:PSVersionTable します。
  • $PWD - 通常どおりアクセスします。
  • $Sender - 通常どおりアクセスします。
  • $ShellId - 代わりにアクセス $Script:ShellId します。
  • $StackTrace - 通常どおりアクセスします。
  • $switch - 通常どおりアクセスします。
  • $this - 通常どおりアクセスします。 クラス メソッドでは、 $this 常にクラスの現在のインスタンスです。 クラスのプロパティとメソッドには、それを使用してアクセスできます。 静的メソッドでは使用できません。
  • $true - 通常どおりアクセスします。

自動変数の詳細については、about_Automatic_Variablesを参照してください

非表示のメソッド

クラスのメソッドは、キーワード (keyword)でhidden宣言することで非表示にすることができます。 非表示のクラス メソッドは次のとおりです。

  • コマンドレットによって返されるクラス メンバーの一覧には Get-Member 含まれません。 非表示のメソッドをGet-Member表示するには、Force パラメーターを使用します。
  • 非表示のメソッドを定義するクラスで入力候補が発生しない限り、タブ補完または IntelliSense には表示されません。
  • クラスのパブリック メンバー。 これらは呼び出して継承できます。 メソッドを非表示にしても、プライベートにはなりません。 前の点で説明したように、メソッドは非表示になります。

Note

メソッドのオーバーロードを非表示にすると、そのメソッドは IntelliSense、入力候補の結果、および既定の出力 Get-Memberから削除されます。

キーワード (keyword)のhidden詳細については、「about_Hidden」を参照してください

静的メソッド

キーワード (keyword)を使用してメソッドを宣言することで、クラスのインスタンスではなくクラス自体に属するメソッドstaticとして定義できます。 静的クラス メソッド:

  • クラスのインスタンス化に関係なく、常に使用できます。
  • クラスのすべてのインスタンス間で共有されます。
  • 常に使用可能です。
  • クラスのインスタンス プロパティにアクセスできません。 静的プロパティにのみアクセスできます。
  • セッションスパン全体に対してライブ。

派生クラス メソッド

基底クラスから派生したクラスは、基底クラスとそのオーバーロードのメソッドを継承します。 基底クラスで定義されているメソッド オーバーロード (非表示のメソッドを含む) は、派生クラスで使用できます。

派生クラスは、クラス定義で再定義することで、継承されたメソッドオーバーロードをオーバーライドできます。 オーバーロードをオーバーライドするには、パラメーターの型が基底クラスと同じである必要があります。 オーバーロードの出力の種類は異なる場合があります。

コンストラクターとは異なり、メソッドは構文を : base(<parameters>) 使用してメソッドの基底クラスオーバーロードを呼び出すことはできません。 派生クラスで再定義されたオーバーロードは、基底クラスによって定義されたオーバーロードを完全に置き換えます。

次の例は、派生クラスでの静的メソッドとインスタンス メソッドの動作を示しています。

基底クラスは次を定義します。

  • 現在の Now() 時刻を返し、 DaysAgo() 過去の日付を返す静的メソッド。
  • インスタンス プロパティ TimeStamp と、 ToString() そのプロパティの文字列表現を返すインスタンス メソッド。 これにより、インスタンスが文字列で使用されると、クラス名ではなく datetime 文字列に変換されます。
  • 2 つのオーバーロードを持つインスタンス メソッド SetTimeStamp() 。 パラメーターを指定せずにメソッドを呼び出すと、TimeStamp現在の時刻に設定されます。 メソッドが DateTime を使用して呼び出されると、TimeStamp がその値に設定されます。
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()
    }
}

次のブロックは、BaseClass から派生したクラスを定義します。

  • DerivedClassA は、オーバーライドなしで BaseClass から継承します。
  • DerivedClassB は、DateTime オブジェクトの代わりに文字列表現を返すために静的メソッドをオーバーライドDaysAgo()します。 また、インスタンス メソッドを ToString() オーバーライドして、タイムスタンプをISO8601日付文字列として返します。
  • DerivedClassC はメソッドのパラメーターなしのオーバーロードを SetTimeStamp() オーバーライドし、パラメーターなしのタイムスタンプを設定すると、現在の日付の 10 日前に日付が設定されます。
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))
    }
}

次のブロックは、定義されたクラスの静的 Now() メソッドの出力を示しています。 派生クラスはメソッドの基底クラスの実装をオーバーライドしないため、出力はすべてのクラスで同じです。

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

次のブロックは、各クラスの DaysAgo() 静的メソッドを呼び出します。 基本実装がオーバーロードされるため、DerivedClassB の出力のみが異なります。

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

次のブロックは、各クラスの新しいインスタンスの文字列表示を示しています。 DerivedClassB表現は、インスタンス メソッドをオーバーロード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

次のブロックは、各インスタンスのインスタンス メソッドをSetTimeStamp()呼び出し、TimeStamp プロパティを特定の日付に設定します。 メソッドのパラメーター化されたオーバーロードをオーバーライドする派生クラスがないため、各インスタンスの日付は同じです。

[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

パラメーターのない最後のブロック呼び出し SetTimeStamp() 。 出力は、DerivedClassC インスタンスの値が他のインスタンスの 10 日前に設定されていることを示しています。

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

Update-TypeData を使用したインスタンス メソッドの定義

クラス定義でメソッドを直接宣言するだけでなく、コマンドレットを使用して静的コンストラクター内のクラスのインスタンスのメソッドを Update-TypeData 定義できます。

このスニペットは、パターンの開始点として使用します。 必要に応じて、山かっこ内のプレースホルダー テキストを置き換えます。

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

ヒント

このコマンドレットは Add-Member 、非静的コンストラクター内のクラスにプロパティとメソッドを追加できますが、このコマンドレットはコンストラクターが呼び出されるたびに実行されます。 静的コンストラクターで使用すると Update-TypeData 、クラスにメンバーを追加するためのコードは、セッションで 1 回だけ実行する必要があります。

既定のパラメーター値と検証属性を使用したメソッドの定義

クラス宣言で直接定義されたメソッドは、メソッド パラメーターに既定値や検証属性を定義できません。 既定値または検証属性を持つクラス メソッドを定義するには、ScriptMethod メンバーとして定義する必要があります。

この例では、CardDeck クラスは、検証属性と Count パラメーターの既定値の両方を使用するメソッドを定義Draw()します。

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.

Exception calling "Eat" with "1" argument(s): "The attribute cannot be
added because variable Count with value 20 would no longer be valid."
At line:1 char:1
+ $Jar.Eat(20)
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationExcep
   tion
    + FullyQualifiedErrorId : ScriptMethodRuntimeException

You ate 6 cookies. There are 4 left.

Note

このパターンは検証属性に対して機能しますが、例外が誤解を招き、属性を追加できないことを参照していることに注意してください。 パラメーターの値を明示的にチェックし、代わりに意味のあるエラーを発生させる方が、ユーザー エクスペリエンスが向上する可能性があります。 そうすることで、ユーザーはエラーが発生した理由と、そのエラーに対して何を行うかを理解できます。

制限事項

PowerShell クラス メソッドには、次の制限があります。

  • メソッド パラメーターでは、検証属性を含む属性を使用できません。

    回避策: メソッド本体のパラメーターを検証属性で再割り当てするか、コマンドレットを使用して静的コンストラクターでメソッドを Update-TypeData 定義します。

  • メソッド パラメーターでは既定値を定義できません。 パラメーターは常に必須です。

    回避策: コマンドレットを使用して、静的コンストラクターでメソッドを Update-TypeData 定義します。

  • メソッドは、非表示の場合でも常にパブリックです。 これらは、クラスが継承されるときにオーバーライドできます。

    回避策: なし。

  • メソッドのオーバーロードが非表示の場合、そのメソッドのすべてのオーバーロードも非表示として扱われます。

    回避策: なし。

関連項目