共用方式為


about_Member-Access_Enumeration

簡短描述

描述當使用成員存取運算符時對集合進行自動列舉。

詳細描述

PowerShell 會維護可列舉的類型清單。 從 PowerShell 3.0 開始,成員存取列舉 功能可改善在可列舉的集合物件上使用成員存取運算符 (.) 的便利性。

成員存取列舉可協助您撰寫更簡單且較短的程序代碼。 您可以對集合物件 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 會列舉該集合中的專案,並在每個列舉專案上使用成員存取運算元。

在屬性的成員存取列舉期間,運算子會針對具有該屬性的每個專案傳回 屬性的值。 如果沒有專案具有指定的 屬性,運算子會傳 $null回 。

在方法的成員存取列舉期間,運算子會嘗試在集合中的每個專案上呼叫 方法。 如果集合中的任何項目沒有指定的方法,運算符會傳 回 MethodNotFound 例外狀況。

警告

在方法的成員存取列舉期間,會在集合中的每個專案上呼叫 方法。 如果您要呼叫的方法進行變更,則會針對集合中的每個項目進行變更。 如果列舉期間發生錯誤,方法只會在錯誤之前列舉的專案上呼叫。 如需其他安全性,請考慮手動列舉專案,並明確處理任何錯誤。

存取無法枚舉物件的成員

當您在不是可列舉集合的物件上使用成員存取運算符時,PowerShell 會叫用成員以傳回該對象的 屬性或輸出值。

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

當您在沒有成員的非可列舉物件上使用成員存取運算符時,PowerShell 會傳回遺漏屬性的 $nullMethodNotFound 遺漏方法的錯誤。

PS> $MyString = 'abc'
PS> $null -eq $MyString.DoesNotExist
True
PS> $MyString.DoesNotExist()
Method invocation failed because [System.String] does not contain a method named 'DoesNotExist'.
At line:1 char:1
+ $MyString.DoesNotExist()
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

存取集合對象的成員

當您在具有成員的集合物件上使用成員存取運算符時,它一律會傳回集合物件的屬性值或方法結果。

存取存在於集合中但不屬於其個別項目的成員

在此範例中,指定的成員存在於集合上,但不存在其中的專案。

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 介面的集合,例如 HashTableOrderedDictionary,有不同的行為。 當您在具有與屬性相同名稱的字典上使用成員存取運算符時,它會傳回索引鍵的值,而不是屬性的值。

您可以使用 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.String 不包含 方法,而不是 System.Collections.Generic.List

只存在於集合中某些專案上的存取方法

當您使用成員存取運算符來存取集合對象上沒有方法的方法,而且集合中只有某些專案具有此方法時,命令會針對集合中沒有 方法的第一個專案傳回 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 是包含兩個元素的陣列:字串的巢狀陣列和單一字串。

# 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 中第二個項目的 Foo() 方法會引發錯誤,因此遍歷會失敗。

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

$example2 中的第二個項目沒有 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 值。

在下列範例中,至少有一個 物件具有參考的屬性。

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 問題 #13752

另請參閱