次の方法で共有


about_Classes_Methods

簡単な説明

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

詳細な説明

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

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

Note

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

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

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

クラス メソッドには、 hidden および static 属性など、任意の数の属性を持つことができます。

構文

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

1 行構文

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

複数行の構文

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

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

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

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 - 出力なしのメソッド

次の使用例は、出力の種類を System.Void としてValidate() メソッドを定義します。 このメソッドは出力を返しません。 代わりに、検証が失敗すると、エラーがスローされます。 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

Exception:
Line |
  20 |              throw $Message
     |              ~~~~~~~~~~~~~~
     | Invalid cube properties ('Height', 'Width'): Cube dimensions must
     | all be positive numbers.

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

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

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

2 番目のオーバーロードには、数値入力のみが含まれます。 $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)

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.

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

$falseがボリュームの0を返すように、Strict パラメーターを使用して静的メソッドを直接呼び出します。

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

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

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

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

次のクラスは、 Shuffle()Deal()の 2 つのメソッドを定義します。 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 以外の明示的な出力型が含まれている場合、メソッドはその型のオブジェクトを返す必要があります。 メソッドは、 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. 必要な検証属性を使用して、パラメーターを同じ変数に再割り当てします。 これは、静的メソッドとインスタンス メソッドの両方で機能します。 このパターンの例については、 Example 4 を参照してください。
  2. パラメーターに対して検証属性を直接使用するScriptMethodを定義するには、Update-TypeDataを使用します。 これはインスタンス メソッドに対してのみ機能します。 詳細については、「Update-TypeData を使用したインスタンス メソッドの定義」セクションを参照してください。

メソッド内の自動変数

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

  • $? - 通常どおりアクセスします。
  • $_ - 通常どおりアクセスします。
  • $args - 代わりに明示的なパラメーター変数を使用してください。
  • $ConsoleFileName - 代わりに $Script:ConsoleFileName としてアクセスします。
  • $Error - 通常どおりアクセスします。
  • $EnabledExperimentalFeatures - 代わりに $Script:EnabledExperimentalFeatures としてアクセスします。
  • $Event - 通常どおりアクセスします。
  • $EventArgs - 通常どおりアクセスします。
  • $EventSubscriber - 通常どおりアクセスします。
  • $ExecutionContext - 代わりに $Script:ExecutionContext としてアクセスします。
  • $false - 通常どおりアクセスします。
  • $foreach - 通常どおりアクセスします。
  • $HOME - 代わりに $Script:HOME としてアクセスします。
  • $Host - 代わりに $Script:Host としてアクセスします。
  • $input - 代わりに明示的なパラメーター変数を使用してください。
  • $IsCoreCLR - 代わりに $Script:IsCoreCLR としてアクセスします。
  • $IsLinux - 代わりに $Script:IsLinux としてアクセスします。
  • $IsMacOS - 代わりに $Script:IsMacOS としてアクセスします。
  • $IsWindows - 代わりに $Script:IsWindows としてアクセスします。
  • $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を参照してください。

非表示のメソッド

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

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

Note

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

hidden キーワードの詳細については、about_Hiddenを参照してください。

静的メソッド

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 から継承します。
  • DerivedClassBDaysAgo() 静的メソッドをオーバーライドして、 DateTime オブジェクトの代わりに文字列表現を返します。 また、 ToString() インスタンス メソッドをオーバーライドして、タイムスタンプをISO8601日付文字列として返します。
  • DerivedClassCSetTimeStamp() メソッドのパラメーターなしのオーバーロードをオーバーライドして、パラメーターを指定せずにタイムスタンプを設定すると、現在の日付の 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.

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.

Note

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

制限事項

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

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

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

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

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

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

    回避策: なし。

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

    回避策: なし。

関連項目