다음을 통해 공유


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 예외를 반환합니다.

Warning

메서드에 대한 멤버 액세스 열거 중에 컬렉션의 각 항목에서 메서드가 호출됩니다. 호출하는 메서드가 변경되면 컬렉션의 모든 항목에 대해 변경됩니다. 열거 중에 오류가 발생하면 메서드는 오류 전에 열거된 항목에서만 호출됩니다. 안전을 위해 항목을 수동으로 열거하고 오류를 명시적으로 처리하는 것이 좋습니다.

열거할 수 없는 개체의 멤버에 액세스

열거 가능한 컬렉션이 아닌 개체에서 멤버 액세스 연산자를 사용하는 경우 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

참고 항목

HashTable 및 OrderedDictionary와 같은 System.Collections.IDictionary 인터페이스를 구현하는 컬렉션의 동작은 다릅니다. 속성과 이름이 같은 키가 있는 사전에서 멤버 액세스 연산자를 사용하면 속성 대신 키의 값이 반환됩니다.

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 문자열의 중첩 배열과 단일 문자열의 두 요소를 포함하는 배열입니다.

# 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

Foo()의 두 번째 항목에 있는 $example2 메서드는 오류가 발생하여 열거가 제대로 수행되지 않습니다.

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참조하세요.

참고 항목