about_Classes

간단한 설명

클래스를 사용하여 사용자 지정 형식을 만드는 방법을 설명합니다.

자세한 설명

버전 5.0부터 PowerShell에는 클래스 및 기타 사용자 정의 형식을 정의하는 공식 구문이 있습니다. 클래스를 추가하면 개발자와 IT 전문가가 광범위한 사용 사례에 대해 PowerShell을 수용할 수 있습니다.

클래스 선언은 런타임에 개체 인스턴스를 만드는 데 사용되는 청사진입니다. 클래스를 정의할 때 클래스 이름은 형식의 이름입니다. 예를 들어 Device라는 클래스를 선언하고 변수 $dev 를 Device의 새 인스턴스로 초기화하는 경우 디바이스$dev 유형의 개체 또는 인스턴스입니다. 디바이스각 인스턴스는 속성에 서로 다른 값을 가질 수 있습니다.

지원되는 시나리오

  • 클래스, 속성, 메서드, 상속 등과 같은 개체 지향 프로그래밍 의미 체계를 사용하여 PowerShell에서 사용자 지정 형식을 정의합니다.
  • PowerShell 언어를 사용하여 DSC 리소스 및 관련 형식을 정의합니다.
  • 변수, 매개 변수 및 사용자 지정 형식 정의를 데코레이트하는 사용자 지정 특성을 정의합니다.
  • 형식 이름으로 catch할 수 있는 사용자 지정 예외를 정의합니다.

구문

정의 구문

클래스 정의는 다음 구문을 사용합니다.

class <class-name> [: [<base-class>][,<interface-list>]] {
    [[<attribute>] [hidden] [static] <property-definition> ...]
    [<class-name>([<constructor-argument-list>])
      {<constructor-statement-list>} ...]
    [[<attribute>] [hidden] [static] <method-definition> ...]
}

인스턴스화 구문

클래스의 인스턴스를 인스턴스화하려면 다음 구문 중 하나를 사용합니다.

[$<variable-name> =] New-Object -TypeName <class-name> [
  [-ArgumentList] <constructor-argument-list>]
[$<variable-name> =] [<class-name>]::new([<constructor-argument-list>])
[$<variable-name> =] [<class-name>]@{[<class-property-hashtable>]}

참고 항목

구문을 사용하는 [<class-name>]::new() 경우 클래스 이름 주위의 대괄호는 필수입니다. 대괄호는 PowerShell에 대한 형식 정의를 신호로 표시합니다.

해시 테이블 구문은 매개 변수를 기대하지 않는 기본 생성자가 있는 클래스에 대해서만 작동합니다. 기본 생성자를 사용하여 클래스의 인스턴스를 만든 다음, 키-값 쌍을 인스턴스 속성에 할당합니다. 해시 테이블의 키가 유효한 속성 이름이 아닌 경우 PowerShell에서 오류가 발생합니다.

예제

예제 1 - 최소 정의

이 예제에서는 사용 가능한 클래스를 만드는 데 필요한 최소 구문을 보여줍니다.

class Device {
    [string]$Brand
}

$dev = [Device]::new()
$dev.Brand = "Fabrikam, Inc."
$dev
Brand
-----
Fabrikam, Inc.

예제 2 - 인스턴스 멤버가 있는 클래스

이 예제에서는 여러 속성, 생성자 및 메서드를 사용하여 Book 클래스를 정의합니다. 정의된 모든 멤버는 정적 멤버가 아닌 인스턴스 멤버입니다. 속성 및 메서드는 클래스의 만든 인스턴스를 통해서만 액세스할 수 있습니다.

class Book {
    # Class properties
    [string]   $Title
    [string]   $Author
    [string]   $Synopsis
    [string]   $Publisher
    [datetime] $PublishDate
    [int]      $PageCount
    [string[]] $Tags
    # Default constructor
    Book() { $this.Init(@{}) }
    # Convenience constructor from hashtable
    Book([hashtable]$Properties) { $this.Init($Properties) }
    # Common constructor for title and author
    Book([string]$Title, [string]$Author) {
        $this.Init(@{Title = $Title; Author = $Author })
    }
    # Shared initializer method
    [void] Init([hashtable]$Properties) {
        foreach ($Property in $Properties.Keys) {
            $this.$Property = $Properties.$Property
        }
    }
    # Method to calculate reading time as 2 minutes per page
    [timespan] GetReadingTime() {
        if ($this.PageCount -le 0) {
            throw 'Unable to determine reading time from page count.'
        }
        $Minutes = $this.PageCount * 2
        return [timespan]::new(0, $Minutes, 0)
    }
    # Method to calculate how long ago a book was published
    [timespan] GetPublishedAge() {
        if (
            $null -eq $this.PublishDate -or
            $this.PublishDate -eq [datetime]::MinValue
        ) { throw 'PublishDate not defined' }

        return (Get-Date) - $this.PublishDate
    }
    # Method to return a string representation of the book
    [string] ToString() {
        return "$($this.Title) by $($this.Author) ($($this.PublishDate.Year))"
    }
}

다음 코드 조각은 클래스의 인스턴스를 만들고 클래스의 동작 방식을 보여 줍니다. Book 클래스의 인스턴스를 만든 후 예제에서는 해당 및 GetPublishedAge() 메서드를 사용하여 GetReadingTime() 책에 대한 메시지를 작성합니다.

$Book = [Book]::new(@{
    Title       = 'The Hobbit'
    Author      = 'J.R.R. Tolkien'
    Publisher   = 'George Allen & Unwin'
    PublishDate = '1937-09-21'
    PageCount   = 310
    Tags        = @('Fantasy', 'Adventure')
})

$Book
$Time = $Book.GetReadingTime()
$Time = @($Time.Hours, 'hours and', $Time.Minutes, 'minutes') -join ' '
$Age  = [Math]::Floor($Book.GetPublishedAge().TotalDays / 365.25)

"It takes $Time to read $Book,`nwhich was published $Age years ago."
Title       : The Hobbit
Author      : J.R.R. Tolkien
Synopsis    :
Publisher   : George Allen & Unwin
PublishDate : 9/21/1937 12:00:00 AM
PageCount   : 310
Tags        : {Fantasy, Adventure}

It takes 10 hours and 20 minutes to read The Hobbit by J.R.R. Tolkien (1937),
which was published 86 years ago.

예제 3 - 정적 멤버가 있는 클래스

이 예제의 BookList 클래스는 예제 2의 Book 클래스를 기반으로 합니다. BookList 클래스는 정적 클래스로 표시할 수 없지만 구현은 Books 정적 속성과 해당 속성을 관리하기 위한 정적 메서드 집합만 정의합니다.

class BookList {
    # Static property to hold the list of books
    static [System.Collections.Generic.List[Book]] $Books
    # Static method to initialize the list of books. Called in the other
    # static methods to avoid needing to explicit initialize the value.
    static [void] Initialize()             { [BookList]::Initialize($false) }
    static [bool] Initialize([bool]$force) {
        if ([BookList]::Books.Count -gt 0 -and -not $force) {
            return $false
        }

        [BookList]::Books = [System.Collections.Generic.List[Book]]::new()

        return $true
    }
    # Ensure a book is valid for the list.
    static [void] Validate([book]$Book) {
        $Prefix = @(
            'Book validation failed: Book must be defined with the Title,'
            'Author, and PublishDate properties, but'
        ) -join ' '
        if ($null -eq $Book) { throw "$Prefix was null" }
        if ([string]::IsNullOrEmpty($Book.Title)) {
            throw "$Prefix Title wasn't defined"
        }
        if ([string]::IsNullOrEmpty($Book.Author)) {
            throw "$Prefix Author wasn't defined"
        }
        if ([datetime]::MinValue -eq $Book.PublishDate) {
            throw "$Prefix PublishDate wasn't defined"
        }
    }
    # Static methods to manage the list of books.
    # Add a book if it's not already in the list.
    static [void] Add([Book]$Book) {
        [BookList]::Initialize()
        [BookList]::Validate($Book)
        if ([BookList]::Books.Contains($Book)) {
            throw "Book '$Book' already in list"
        }

        $FindPredicate = {
            param([Book]$b)

            $b.Title -eq $Book.Title -and
            $b.Author -eq $Book.Author -and
            $b.PublishDate -eq $Book.PublishDate
        }.GetNewClosure()
        if ([BookList]::Books.Find($FindPredicate)) {
            throw "Book '$Book' already in list"
        }

        [BookList]::Books.Add($Book)
    }
    # Clear the list of books.
    static [void] Clear() {
      [BookList]::Initialize()
      [BookList]::Books.Clear()
    }
    # Find a specific book using a filtering scriptblock.
    static [Book] Find([scriptblock]$Predicate) {
        [BookList]::Initialize()
        return [BookList]::Books.Find($Predicate)
    }
    # Find every book matching the filtering scriptblock.
    static [Book[]] FindAll([scriptblock]$Predicate) {
        [BookList]::Initialize()
        return [BookList]::Books.FindAll($Predicate)
    }
    # Remove a specific book.
    static [void] Remove([Book]$Book) {
        [BookList]::Initialize()
        [BookList]::Books.Remove($Book)
    }
    # Remove a book by property value.
    static [void] RemoveBy([string]$Property, [string]$Value) {
        [BookList]::Initialize()
        $Index = [BookList]::Books.FindIndex({
            param($b)
            $b.$Property -eq $Value
        }.GetNewClosure())
        if ($Index -ge 0) {
            [BookList]::Books.RemoveAt($Index)
        }
    }
}

이제 BookList정의되었으므로 이전 예제의 책을 목록에 추가할 수 있습니다.

$null -eq [BookList]::Books

[BookList]::Add($Book)

[BookList]::Books
True

Title       : The Hobbit
Author      : J.R.R. Tolkien
Synopsis    :
Publisher   : George Allen & Unwin
PublishDate : 9/21/1937 12:00:00 AM
PageCount   : 310
Tags        : {Fantasy, Adventure}

다음 코드 조각은 클래스에 대한 정적 메서드를 호출합니다.

[BookList]::Add([Book]::new(@{
    Title       = 'The Fellowship of the Ring'
    Author      = 'J.R.R. Tolkien'
    Publisher   = 'George Allen & Unwin'
    PublishDate = '1954-07-29'
    PageCount   = 423
    Tags        = @('Fantasy', 'Adventure')
}))

[BookList]::Find({
    param ($b)

    $b.PublishDate -gt '1950-01-01'
}).Title

[BookList]::FindAll({
    param($b)

    $b.Author -match 'Tolkien'
}).Title

[BookList]::Remove($Book)
[BookList]::Books.Title

[BookList]::RemoveBy('Author', 'J.R.R. Tolkien')
"Titles: $([BookList]::Books.Title)"

[BookList]::Add($Book)
[BookList]::Add($Book)
The Fellowship of the Ring

The Hobbit
The Fellowship of the Ring

The Fellowship of the Ring

Titles:

Exception:
Line |
  84 |              throw "Book '$Book' already in list"
     |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Book 'The Hobbit by J.R.R. Tolkien (1937)' already in list

예제 4 - Runspace 선호도를 사용 또는 사용하지 않는 클래스 정의

ShowRunspaceId() 다른 스레드 ID를 보고하지만 동일한 Runspace ID를 보고하는 메서드 [UnsafeClass] 입니다. 결국 세션 상태가 손상되어 다음과 같은 Global scope cannot be removed오류가 발생합니다.

# Class definition with Runspace affinity (default behavior)
class UnsafeClass {
    static [object] ShowRunspaceId($val) {
        return [PSCustomObject]@{
            ThreadId   = [Threading.Thread]::CurrentThread.ManagedThreadId
            RunspaceId = [runspace]::DefaultRunspace.Id
        }
    }
}

$unsafe = [UnsafeClass]::new()

while ($true) {
    1..10 | ForEach-Object -Parallel {
        Start-Sleep -ms 100
        ($using:unsafe)::ShowRunspaceId($_)
    }
}

참고 항목

이 예제는 무한 루프에서 실행됩니다. Ctrl+C를 입력하여 실행을 중지합니다.

ShowRunspaceId() 다른 스레드 및 Runspace ID를 보고하는 메서드 [SafeClass] 입니다.

# Class definition with NoRunspaceAffinity attribute
[NoRunspaceAffinity()]
class SafeClass {
    static [object] ShowRunspaceId($val) {
        return [PSCustomObject]@{
            ThreadId   = [Threading.Thread]::CurrentThread.ManagedThreadId
            RunspaceId = [runspace]::DefaultRunspace.Id
        }
    }
}

$safe = [SafeClass]::new()

while ($true) {
    1..10 | ForEach-Object -Parallel {
        Start-Sleep -ms 100
        ($using:safe)::ShowRunspaceId($_)
    }
}

참고 항목

이 예제는 무한 루프에서 실행됩니다. Ctrl+C를 입력하여 실행을 중지합니다.

클래스 속성

속성은 클래스 범위에서 선언된 변수입니다. 속성은 기본 제공 형식이거나 다른 클래스의 인스턴스일 수 있습니다. 클래스에는 0개 이상의 속성이 있을 수 있습니다. 클래스에는 최대 속성 수가 없습니다.

자세한 내용은 about_Classes_Properties 참조하세요.

클래스 메서드

메서드는 클래스가 수행할 수 있는 작업을 정의합니다. 메서드는 입력 데이터를 지정하는 매개 변수를 사용할 수 있습니다. 메서드는 항상 출력 형식을 정의합니다. 메서드가 출력을 반환하지 않는 경우 Void 출력 형식이 있어야 합니다. 메서드가 출력 형식을 명시적으로 정의하지 않으면 메서드의 출력 형식은 Void입니다.

자세한 내용은 about_Classes_Methods 참조하세요.

클래스 생성자

생성자를 사용하면 클래스의 인스턴스를 만들 때 기본값을 설정하고 개체 논리의 유효성을 검사할 수 있습니다. 생성자의 이름은 클래스와 같습니다. 생성자에는 새 개체의 데이터 멤버를 초기화하는 매개 변수가 있을 수 있습니다.

자세한 내용은 about_Classes_Constructors 참조하세요.

숨겨진 키워드(keyword)

hidden 키워드(keyword) 클래스 멤버를 숨깁니다. 멤버는 여전히 사용자가 액세스할 수 있으며 개체를 사용할 수 있는 모든 범위에서 사용할 수 있습니다. 숨겨진 멤버는 cmdlet에서 Get-Member 숨겨져 있으며, 클래스 정의 외부의 탭 완성 또는 IntelliSense를 사용하여 표시할 수 없습니다.

hidden 키워드(keyword) 클래스 자체가 아닌 클래스 멤버에만 적용됩니다.

숨겨진 클래스 멤버는 다음과 같습니다.

  • 클래스의 기본 출력에 포함되지 않습니다.
  • cmdlet에서 반환 Get-Member 하는 클래스 멤버 목록에 포함되지 않습니다. 숨겨진 멤버를 Get-Member표시하려면 Force 매개 변수를 사용합니다.
  • 숨겨진 멤버를 정의하는 클래스에서 완료가 발생하지 않는 한 탭 완성 또는 IntelliSense에 표시되지 않습니다.
  • 클래스의 공용 멤버입니다. 액세스, 상속 및 수정할 수 있습니다. 멤버를 숨기면 비공개로 만들어지지 않습니다. 이전 지점에 설명된 대로 멤버만 숨깁니다.

참고 항목

메서드에 대한 오버로드를 숨기면 해당 메서드가 IntelliSense, 완료 결과 및 기본 출력 Get-Member에서 제거됩니다. 생성자를 new() 숨기면 IntelliSense 및 완료 결과에서 옵션이 제거됩니다.

키워드(keyword) 대한 자세한 내용은 about_Hidden 참조하세요. 숨겨진 속성에 대한 자세한 내용은 about_Classes_Properties 참조하세요. 숨겨진 메서드에 대한 자세한 내용은 about_Classes_Methods 참조하세요. 숨겨진 생성자에 대한 자세한 내용은 about_Classes_Constructors 참조하세요.

정적 키워드(keyword)

static 키워드(keyword) 클래스에 있고 인스턴스가 필요하지 않은 속성 또는 메서드를 정의합니다.

정적 속성은 클래스 인스턴스화와 관계없이 항상 사용할 수 있습니다. 정적 속성은 클래스의 모든 인스턴스에서 공유됩니다. 정적 메서드는 항상 사용할 수 있습니다. 모든 정적 속성은 전체 세션 범위에 대해 라이브로 표시됩니다.

static 키워드(keyword) 클래스 자체가 아닌 클래스 멤버에만 적용됩니다.

정적 속성에 대한 자세한 내용은 about_Classes_Properties 참조하세요. 정적 메서드에 대한 자세한 내용은 about_Classes_Methods 참조하세요. 정적 생성자에 대한 자세한 내용은 about_Classes_Constructors 참조하세요.

PowerShell 클래스의 상속

기존 클래스에서 파생되는 새 클래스를 만들어 클래스를 확장할 수 있습니다. 파생 클래스는 기본 클래스의 속성과 메서드를 상속합니다. 필요에 따라 기본 클래스 멤버를 추가하거나 재정의할 수 있습니다.

PowerShell은 여러 상속을 지원하지 않습니다. 클래스는 둘 이상의 클래스에서 직접 상속할 수 없습니다.

클래스는 계약을 정의하는 인터페이스에서 상속할 수도 있습니다. 인터페이스에서 상속되는 클래스는 해당 계약을 구현해야 합니다. 이 경우 해당 인터페이스를 구현하는 다른 클래스와 마찬가지로 클래스를 사용할 수 있습니다.

기본 클래스에서 상속되거나 인터페이스를 구현하는 클래스를 파생시키는 방법에 대한 자세한 내용은 about_Classes_Inheritance 참조하세요.

NoRunspaceAffinity 특성

Runspace는 PowerShell에서 호출하는 명령에 대한 운영 환경입니다. 이 환경에는 현재 있는 명령 및 데이터와 현재 적용되는 언어 제한이 포함됩니다.

기본적으로 PowerShell 클래스는 생성된 Runspace와 연결됩니다. PowerShell 클래스를 ForEach-Object -Parallel 사용하는 것은 안전하지 않습니다. 클래스의 메서드 호출은 생성된 Runspace로 다시 마샬링되어 Runspace상태가 손상되거나 교착 상태가 발생할 수 있습니다.

클래스 정의에 NoRunspaceAffinity 특성을 추가하면 PowerShell 클래스가 특정 Runspace와 연결되지 않습니다. 인스턴스 및 정적 메서드 호출은 실행 중인 스레드의 Runspace와 스레드의 현재 세션 상태를 사용합니다.

특성이 PowerShell 7.4에 추가되었습니다.

특성이 있고 없는 클래스의 동작 차이에 대한 그림은 예제 4NoRunspaceAffinity 참조하세요.

형식 가속기를 사용하여 클래스 내보내기

기본적으로 PowerShell 모듈은 PowerShell에 정의된 클래스 및 열거형을 자동으로 내보내지 않습니다. 문을 호출하지 않고는 모듈 외부에서 사용자 지정 형식을 using module 사용할 수 없습니다.

그러나 모듈에서 형식 가속기를 추가하는 경우 사용자가 모듈을 가져온 후 해당 형식 가속기를 세션에서 즉시 사용할 수 있습니다.

참고 항목

세션에 형식 가속기를 추가하면 내부(공용이 아님) API가 사용됩니다. 이 API를 사용하면 충돌이 발생할 수 있습니다. 모듈을 가져올 때 이름이 같은 형식 가속기가 이미 있는 경우 아래에 설명된 패턴은 오류를 throw합니다. 또한 세션에서 모듈을 제거할 때 형식 가속기를 제거합니다.

이 패턴은 세션에서 형식을 사용할 수 있도록 합니다. VS Code에서 스크립트 파일을 작성할 때 IntelliSense 또는 완성에는 영향을 주지 않습니다. VS Code에서 사용자 지정 형식에 대한 IntelliSense 및 완성 제안을 얻으려면 스크립트 맨 위에 문을 추가 using module 해야 합니다.

다음 패턴에서는 PowerShell 클래스 및 열거형을 모듈의 형식 가속기로 등록하는 방법을 보여 줍니다. 형식 정의 후에 루트 스크립트 모듈에 코드 조각을 추가합니다. 변수에 $ExportableTypes 사용자가 모듈을 가져올 때 사용할 수 있도록 하려는 각 형식이 포함되어 있는지 확인합니다. 다른 코드는 편집할 필요가 없습니다.

# Define the types to export with type accelerators.
$ExportableTypes =@(
    [DefinedTypeName]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
    'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
    if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
        $Message = @(
            "Unable to register type accelerator '$($Type.FullName)'"
            'Accelerator already exists.'
        ) -join ' - '

        throw [System.Management.Automation.ErrorRecord]::new(
            [System.InvalidOperationException]::new($Message),
            'TypeAcceleratorAlreadyExists',
            [System.Management.Automation.ErrorCategory]::InvalidOperation,
            $Type.FullName
        )
    }
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
    $TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
    foreach($Type in $ExportableTypes) {
        $TypeAcceleratorsClass::Remove($Type.FullName)
    }
}.GetNewClosure()

사용자가 모듈을 가져올 때 세션의 형식 가속기에 추가된 모든 형식을 IntelliSense 및 완성에 즉시 사용할 수 있습니다. 모듈이 제거되면 형식 가속기도 마찬가지입니다.

PowerShell 모듈에서 수동으로 클래스 가져오기

Import-Module 문은 #requires 모듈에서 정의한 대로 모듈 함수, 별칭 및 변수만 가져옵니다. 클래스는 가져오지 않습니다.

모듈이 클래스 및 열거형을 정의하지만 해당 형식에 대한 형식 가속기를 추가하지 않는 경우 문을 사용하여 using module 클래스를 가져옵니다.

이 문은 스크립트 모듈 또는 이 using module 진 모듈의 루트 모듈(ModuleToProcess)에서 클래스 및 열거형을 가져옵니다. 중첩된 모듈에 정의된 클래스 또는 루트 모듈에 점 소스가 지정된 스크립트에 정의된 클래스를 일관되게 가져오지 않습니다. 루트 모듈에서 직접 모듈 외부의 사용자가 사용할 수 있도록 하려는 클래스를 정의합니다.

문에 대한 using 자세한 내용은 about_Using 참조하세요.

개발 중에 새로 변경된 코드 로드

스크립트 모듈을 개발하는 동안 코드를 변경한 다음 Force 매개 변수를 사용하여 Import-Module 모듈의 새 버전을 로드하는 것이 일반적입니다. 모듈 다시 로드는 루트 모듈의 함수 변경에 대해서만 작동합니다. Import-Module 는 중첩된 모듈을 다시 로드하지 않습니다. 또한 업데이트된 클래스를 로드할 수 있는 방법은 없습니다.

최신 버전을 실행하려면 새 세션을 시작해야 합니다. PowerShell에서 정의되고 문으로 using 가져온 클래스 및 열거형은 언로드할 수 없습니다.

또 다른 일반적인 개발 방법은 코드를 다른 파일로 분리하는 것입니다. 한 파일에 다른 모듈에 정의된 클래스를 사용하는 함수가 있는 경우 이 문을 사용하여 using module 함수에 필요한 클래스 정의가 있는지 확인해야 합니다.

PSReference 형식은 클래스 멤버에서 지원되지 않습니다.

[ref] 형식 가속기는 PSReference 클래스의 약식입니다. 클래스 멤버를 형식 캐스팅하는 데 사용하면 [ref] 자동으로 실패합니다. 매개 변수를 사용하는 [ref] API는 클래스 멤버와 함께 사용할 수 없습니다. PSReference 클래스는 COM 개체를 지원하도록 설계되었습니다. COM 개체에는 참조로 값을 전달해야 하는 경우가 있습니다.

자세한 내용은 PSReference 클래스를 참조 하세요.

제한 사항

다음 목록에는 PowerShell 클래스를 정의하기 위한 제한 사항과 이러한 제한 사항(있는 경우)에 대한 해결 방법이 포함되어 있습니다.

일반적인 제한 사항

  • 클래스 멤버는 PSReference를 해당 형식으로 사용할 수 없습니다.

    해결 방법: 없음.

  • PowerShell 클래스는 세션에서 언로드하거나 다시 로드할 수 없습니다.

    해결 방법: 새 세션을 시작합니다.

  • 모듈에 정의된 PowerShell 클래스는 자동으로 가져오지 않습니다.

    해결 방법: 루트 모듈의 형식 가속기 목록에 정의된 형식을 추가합니다. 이렇게 하면 모듈 가져오기에서 형식을 사용할 수 있습니다.

  • hiddenstatic 키워드(keyword) 클래스 정의가 아닌 클래스 멤버에만 적용됩니다.

    해결 방법: 없음.

  • 기본적으로 PowerShell 클래스는 Runspace에서 병렬 실행에서 사용하는 것이 안전하지 않습니다. 클래스에서 메서드를 호출할 때 PowerShell은 호출을 클래스가 만들어진 Runspace로 다시 마샬링합니다. 그러면 Runspace상태가 손상되거나 교착 상태가 발생할 수 있습니다.

    해결 방법: 클래스 선언에 NoRunspaceAffinity 특성을 추가합니다.

생성자 제한 사항

  • 생성자 체인은 구현되지 않습니다.

    해결 방법: 숨겨진 Init() 메서드를 정의하고 생성자 내에서 호출합니다.

  • 생성자 매개 변수는 유효성 검사 특성을 비롯한 특성을 사용할 수 없습니다.

    해결 방법: 유효성 검사 특성을 사용하여 생성자 본문의 매개 변수를 다시 할당합니다.

  • 생성자 매개 변수는 기본값을 정의할 수 없습니다. 매개 변수는 항상 필수입니다.

    해결 방법: 없음.

  • 생성자의 오버로드가 숨겨지면 생성자에 대한 모든 오버로드도 숨김으로 처리됩니다.

    해결 방법: 없음.

메서드 제한 사항

  • 메서드 매개 변수는 유효성 검사 특성을 비롯한 특성을 사용할 수 없습니다.

    해결 방법: 유효성 검사 특성을 사용하여 메서드 본문의 매개 변수를 다시 할당하거나 cmdlet을 사용하여 정적 생성자의 메서드를 Update-TypeData 정의합니다.

  • 메서드 매개 변수는 기본값을 정의할 수 없습니다. 매개 변수는 항상 필수입니다.

    해결 방법: cmdlet을 사용하여 정적 생성자에서 메서드를 Update-TypeData 정의합니다.

  • 메서드는 숨겨진 경우에도 항상 공용입니다. 클래스가 상속될 때 재정의할 수 있습니다.

    해결 방법: 없음.

  • 메서드의 오버로드가 숨겨지면 해당 메서드의 모든 오버로드도 숨김으로 처리됩니다.

    해결 방법: 없음.

속성 제한 사항

  • 정적 속성은 항상 변경할 수 있습니다. PowerShell 클래스는 변경할 수 없는 정적 속성을 정의할 수 없습니다.

    해결 방법: 없음.

  • 클래스 속성 특성 인수는 상수여야 하므로 속성은 ValidateScript 특성을 사용할 수 없습니다.

    해결 방법: ValidateArgumentsAttribute 형식에서 상속되는 클래스를 정의하고 대신 해당 특성을 사용합니다.

  • 직접 선언된 속성은 사용자 지정 getter 및 setter 구현을 정의할 수 없습니다.

    해결 방법: 숨겨진 속성을 정의하고 표시되는 getter 및 setter 논리를 정의하는 데 사용합니다 Update-TypeData .

  • 속성은 별칭 특성을 사용할 수 없습니다. 이 특성은 매개 변수, cmdlet 및 함수에만 적용됩니다.

    해결 방법: cmdlet을 Update-TypeData 사용하여 클래스 생성자에서 별칭을 정의합니다.

  • PowerShell 클래스가 cmdlet을 사용하여 JSON으로 ConvertTo-Json 변환되는 경우 출력 JSON에는 숨겨진 속성과 해당 값이 모두 포함됩니다.

    해결 방법: 없음

상속 제한 사항

  • PowerShell은 스크립트 코드에서 인터페이스 정의를 지원하지 않습니다.

    해결 방법: C#에서 인터페이스를 정의하고 인터페이스를 정의하는 어셈블리를 참조합니다.

  • PowerShell 클래스는 하나의 기본 클래스에서만 상속할 수 있습니다.

    해결 방법: 클래스 상속은 전이적입니다. 파생 클래스는 다른 파생 클래스에서 상속하여 기본 클래스의 속성과 메서드를 가져올 수 있습니다.

  • 제네릭 클래스 또는 인터페이스에서 상속하는 경우 제네릭에 대한 형식 매개 변수가 이미 정의되어 있어야 합니다. 클래스는 클래스 또는 인터페이스에 대한 형식 매개 변수로 자신을 정의할 수 없습니다.

    해결 방법: 제네릭 기본 클래스 또는 인터페이스에서 파생하려면 다른 .psm1 파일에서 사용자 지정 형식을 정의하고 문을 사용하여 using module 형식을 로드합니다. 제네릭에서 상속할 때 사용자 지정 형식이 형식 매개 변수로 사용할 수 있는 해결 방법은 없습니다.

참고 항목