ja-JP/about_Member-Access_Enumeration.help.txt

TOPIC
    about_Member-Access_Enumeration

簡単な説明
    メンバーアクセス演算子を使用したときに列挙可能なコレクションが自動的に
    列挙される動作について説明します。

詳細な説明
    PowerShell は列挙可能な型の一覧を保持しています。PowerShell 3.0 以降、
    メンバーアクセス列挙 (member-access enumeration) 機能により、列挙可能な
    コレクションオブジェクトに対してメンバーアクセス演算子 (.) を使う際の
    利便性が向上しました。

    メンバーアクセス列挙を使うと、より簡潔で短いコードを記述できます。
    コレクションオブジェクトを ForEach-Object にパイプしたり、ForEach()
    組み込みメソッドを使ってコレクション内の各項目のメンバーにアクセスする
    代わりに、コレクションオブジェクトに対してメンバーアクセス演算子を
    使用できます。

    次の例はいずれも同じ結果になります。最後の例ではメンバーアクセス演算子
    の使用方法を示しています。

        PS> Get-Service -Name event* | ForEach-Object -Process { $_.DisplayName }
        Windows Event Log
        COM+ Event System
        PS> (Get-Service -Name event*).ForEach({ $_.DisplayName })
        Windows Event Log
        COM+ Event System
        PS> (Get-Service -Name event*).DisplayName
        Windows Event Log
        COM+ Event System

    メモ: メンバーアクセス演算子を使ってコレクション内の各項目のプロパティ
    の値を取得することはできますが、それらを直接設定することはできません。
    詳細については about_Arrays を参照してください。メンバーアクセス列挙は
    利便性のための機能です。各列挙方法の間には、わずかな動作上およびパフォー
    マンス上の違いが存在することがあります。

    オブジェクトに対してメンバーアクセス演算子を使用し、指定したメンバーが
    そのオブジェクトに存在する場合、そのメンバーが呼び出されます。指定した
    メンバーを持たないコレクションオブジェクトに対してメンバーアクセス演算子
    を使用すると、PowerShell はそのコレクション内の項目を列挙し、列挙された
    各項目に対してメンバーアクセス演算子を使用します。

    プロパティに対するメンバーアクセス列挙では、演算子はそのプロパティを
    持つ各項目についてプロパティの値を返します。そのプロパティを持つ項目が
    1 つもない場合、演算子は $null を返します。

    メソッドに対するメンバーアクセス列挙では、演算子はコレクション内の各
    項目に対してそのメソッドの呼び出しを試みます。コレクション内のいずれか
    の項目が指定したメソッドを持たない場合、演算子は MethodNotFound 例外を
    返します。

    警告: メソッドに対するメンバーアクセス列挙では、メソッドはコレクション
    内の各項目に対して呼び出されます。呼び出すメソッドが変更を加えるもので
    ある場合、その変更はコレクション内のすべての項目に対して行われます。
    列挙中にエラーが発生した場合、メソッドはエラー発生前に列挙された項目に
    対してのみ呼び出されています。より安全にするには、項目を手動で列挙し、
    エラーを明示的に処理することを検討してください。

列挙不可能なオブジェクトのメンバーへのアクセス
    列挙可能なコレクションではないオブジェクトに対してメンバーアクセス演算子
    を使用すると、PowerShell はそのメンバーを呼び出し、そのオブジェクトの
    プロパティの値またはメソッドの出力を返します。

        PS> $MyString = 'abc'
        PS> $MyString.Length
        3
        PS> $MyString.ToUpper()
        ABC

    そのメンバーを持たない列挙不可能なオブジェクトに対してメンバーアクセス
    演算子を使用すると、PowerShell は存在しないプロパティに対しては $null
    を、存在しないメソッドに対しては MethodNotFound エラーを返します。

        PS> $MyString = 'abc'
        PS> $null -eq $MyString.DoesNotExist
        True
        PS> $MyString.DoesNotExist()
        InvalidOperation: Method invocation failed because [System.String] does not contain a method named 'DoesNotExist'.

コレクションオブジェクトのメンバーへのアクセス
    そのメンバーを持つコレクションオブジェクトに対してメンバーアクセス演算子
    を使用すると、常にコレクションオブジェクトのプロパティ値またはメソッド
    結果が返されます。

  コレクションには存在するが項目には存在しないメンバーへのアクセス
    次の例では、指定したメンバーはコレクションには存在しますが、コレクション
    内の項目には存在しません。

        PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
        PS> $Collection.IsReadOnly
        False
        PS> $Collection.Add('c')
        PS> $Collection
        a
        b
        c

  コレクションと項目の両方に存在するメンバーへのアクセス
    この例では、指定したメンバーはコレクションとその項目の両方に存在します。
    コレクションに対してメンバーアクセス演算子を使用した結果と、
    ForEach-Object でコレクションの項目に対してメンバーアクセス演算子を
    使用した結果を比較してください。コレクションに対しては、演算子はコレク
    ションオブジェクトのプロパティ値またはメソッド結果を返し、その項目の
    値は返しません。

        PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
        PS> $Collection.Count
        3
        PS> $Collection | ForEach-Object -Process { $_.Count }
        1
        1
        1
        PS> $Collection.ToString()
        System.Collections.Generic.List`1[System.String]
        PS> $Collection | ForEach-Object -Process { $_.ToString() }
        a
        b
        c

    メモ: System.Collections.IDictionary インターフェイスを実装するコレク
    ション (HashTable や OrderedDictionary など) は動作が異なります。
    プロパティと同じ名前のキーを持つディクショナリに対してメンバーアクセス
    演算子を使用すると、プロパティの値ではなくキーの値が返されます。

    ディクショナリオブジェクトのプロパティ値には psbase 組み込みメンバーを
    使ってアクセスできます。たとえば、キー名が keys であり、HashTable の
    キーのコレクションを返したい場合は、次の構文を使用します。

        $hashtable.psbase.Keys

  コレクション自体には存在せずすべての項目に存在するメンバーへのアクセス
    そのメンバーを持たないが項目はそれを持つコレクションオブジェクトに対して
    メンバーアクセス演算子を使用すると、PowerShell はコレクション内の項目を
    列挙し、各項目のプロパティ値またはメソッド結果を返します。

        PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
        PS> $Collection.Length
        1
        1
        1
        PS> $Collection.ToUpper()
        A
        B
        C

  コレクションにも項目にも存在しないメンバーへのアクセス
    そのメンバーを持たず、項目もそれを持たないコレクションオブジェクトに
    対してメンバーアクセス演算子を使用すると、プロパティを指定した場合は
    $null を、メソッドを指定した場合は MethodNotFound エラーを返します。

        PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
        PS> $null -eq $Collection.DoesNotExist
        True
        PS> $Collection.DoesNotExist()
        InvalidOperation: Method invocation failed because [System.String] does not
        contain a method named 'DoesNotExist'.

    コレクションオブジェクトがそのメンバーを持たないため、PowerShell は
    コレクション内の項目を列挙しました。MethodNotFound エラーが、
    System.Collections.Generic.List ではなく System.String にそのメソッドが
    含まれていないことを示している点に注目してください。

  一部の項目にのみ存在するメソッドへのアクセス
    そのメソッドを持たず、コレクション内の一部の項目のみがそれを持つコレク
    ションオブジェクトに対してメンバーアクセス演算子でメソッドにアクセス
    すると、そのメソッドを持たないコレクション内の最初の項目について
    MethodNotFound エラーが返されます。一部の項目でメソッドが呼び出されても、
    返されるのはエラーのみです。

        PS> @('a', 1, 'c').ToUpper()
        InvalidOperation: Method invocation failed because [System.Int32] does not
        contain a method named 'ToUpper'.

  一部の項目にのみ存在するプロパティへのアクセス
    そのプロパティを持たず、コレクション内の一部の項目のみがそれを持つコレク
    ションオブジェクトに対してメンバーアクセス演算子でプロパティにアクセス
    すると、そのプロパティを持つコレクション内の各項目についてプロパティの
    値が返されます。

        PS> $CapitalizedProperty = @{
            MemberType = 'ScriptProperty'
            Name = 'Capitalized'
            Value = { $this.ToUpper() }
            PassThru = $true
        }
        PS> [System.Collections.Generic.List[Object]]$MixedCollection = @(
            'a'
            ('b' | Add-Member @CapitalizedProperty)
            ('c' | Add-Member @CapitalizedProperty)
            'd'
        )
        PS> $MixedCollection.Capitalized
        B
        C

  入れ子になったコレクションのメンバーへのアクセス
    列挙可能なコレクションが入れ子のコレクションを含む場合、各入れ子の
    コレクションに対してメンバーアクセス列挙が適用されます。

    たとえば、$a は 2 つの要素 (文字列の入れ子配列と 1 つの文字列) を含む
    配列です。

        # 配列内の項目の数を取得します。
        PS> $a.Count
        2
        # 各入れ子項目内の項目の数を取得します。
        PS> $a.GetEnumerator().Count
        2
        1
        # 入れ子配列内のすべての項目に対して ToUpper() メソッドを呼び出します。
        PS> $a = @(, ('bar', 'baz'), 'foo')
        PS> $a.ToUpper()
        BAR
        BAZ
        FOO

    メンバーアクセス演算子を使用すると、PowerShell は $a 内の項目を列挙し、
    すべての項目に対して ToUpper() メソッドを呼び出します。

注意事項
    前述のとおり、各列挙方法の間には、わずかな動作上およびパフォーマンス上の
    違いが存在することがあります。

  エラーにより出力が失われる
    メンバーアクセス列挙がエラーによって終了されると、それより前の成功した
    メソッド呼び出しの出力は返されません。終了させるエラー条件には次のものが
    あります。

    - 列挙されたオブジェクトがアクセスされたメソッドを持たない
    - アクセスされたメソッドが終了エラーを発生させる

    次の例を考えてみます。

        class Class1 { [Object] Foo() { return 'Bar' } }
        class Class2 { [void] Foo() { throw 'Error' } }
        class Class3 {}

        $example1 = ([Class1]::new(), [Class1]::new())
        $example2 = ([Class1]::new(), [Class2]::new())
        $example3 = ([Class1]::new(), [Class3]::new())

    $example1 の両方の項目は Foo() メソッドを持つため、メソッド呼び出しは
    成功します。

        PS> $example1.Foo()
        Bar
        Bar

    $example2 の 2 番目の項目の Foo() メソッドはエラーをスローするため、
    列挙は失敗します。

        PS> $example2.Foo()
        Exception:
        Line |
           2 | class Class2 { [void] Foo() { throw 'Error' } }
             | ~~~~~~~~~~~~~
             | Error

    $example3 の 2 番目の項目は Foo() メソッドを持たないため、列挙は失敗
    します。

        PS> $example3.Foo()
        InvalidOperation: Method invocation failed because [Class3] does not contain
        a method named 'Foo'.

    これを ForEach-Object を使った列挙と比較します。

        PS> $example2 | ForEach-Object -MemberName Foo
        Bar
        ForEach-Object: Exception calling "Foo" with "0" argument(s): "Error"
        PS> $example3 | ForEach-Object -MemberName Foo
        Bar

    出力には配列内の最初の項目に対する Foo() の成功した呼び出しが表示されて
    いる点に注目してください。

  PSCustomObject インスタンスを含むコレクション
    オブジェクトのコレクションが PSCustomObject 項目のインスタンスを含む
    場合、アクセスされたプロパティが存在しないと、PowerShell は予期せず
    $null 値を返します。

    次の例では、少なくとも 1 つのオブジェクトが参照されたプロパティを
    持っています。

        PS> $foo = [pscustomobject]@{ Foo = 'Foo' }
        PS> $bar = [pscustomobject]@{ Bar = 'Bar' }
        PS> $baz = [pscustomobject]@{ Baz = 'Baz' }
        PS> ConvertTo-Json ($foo, $bar, $baz).Foo
        [
          "Foo",
          null,
          null
        ]
        PS> ConvertTo-Json ((Get-Process -Id $PID), $foo).Name
        [
          "pwsh",
          null
        ]

    指定したプロパティを持つ項目について、PowerShell が単一のオブジェクトを
    返すことを期待するでしょう。しかし実際には、PowerShell はそのプロパティ
    を持たない各項目についても $null 値を返します。

    この動作の詳細については、PowerShell の Issue #13752 を参照してください。

関連項目
    about_Arrays
    about_Intrinsic_Members
    about_Methods
    about_Operators
    about_Properties

----
原文: PowerShell-Docs (CC BY 4.0) の翻訳 / PSHelpJaJP