次の方法で共有


about_Member-Access_Enumeration

簡単な説明

メンバー アクセス演算子を使用する場合のコレクションの自動列挙について説明します。

詳細な説明

PowerShell では、列挙可能な型の一覧が保持されます。 PowerShell 3.0 以降では、メンバー アクセス列挙 機能により、列挙可能なコレクション オブジェクトに対してメンバー アクセス演算子 (.) を使用する利便性が向上しました。

メンバー アクセス列挙は、よりシンプルで短いコードを記述するのに役立ちます。 コレクション オブジェクトをパイプ処理して ForEach-Object したり、 ForEach()intrinsic メソッドを使用したり コレクション内の各項目のメンバーにアクセスしたりする代わりに、コレクション オブジェクトのメンバー アクセス演算子を使用できます。

次の例では、同じ結果が生成されます。 最後の例では、メンバー アクセス演算子の使用方法を示します。

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

Note

メンバー アクセス演算子を使用すると、コレクション内の項目のプロパティの値を取得できますが、それを使用して直接設定することはできません。 詳細については、 about_Arraysを参照してください。 メンバー アクセス列挙は便利な機能です。 さまざまな列挙メソッドには、微妙な動作とパフォーマンスの違いがあります。

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

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

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

警告

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

列挙不可能なオブジェクトのメンバーにアクセスする

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

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

メンバーを持たない列挙可能でないオブジェクトでメンバー アクセス演算子を使用すると、不足しているプロパティの $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

Note

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

ディクショナリ オブジェクトのプロパティ値には、 psbaseintrinsic メンバーを使用してアクセスできます。 たとえば、キー名が 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 は、文字列の入れ子になった配列と 1 つの文字列の 2 つの要素を含む配列です。

# Get the count of items in the array.
PS> $a.Count
2
# Get the count of items in each nested item.
PS> $a.GetEnumerator().Count
2
1
# Call the ToUpper() method on all items in the nested array.
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

$example2 の 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 は、アクセスされたプロパティが見つからないときに予期せず 値を再び読み込みます。

次の例では、少なくとも 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 は、プロパティが指定されたアイテムの 1 つのオブジェクトを返す必要があります。 代わりに、PowerShell は、プロパティを持たない各項目の $null 値も返します。

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

参照