Condividi tramite


about_Classes

Breve descrizione

Descrive come è possibile usare le classi per creare tipi personalizzati.

Descrizione lunga

A partire dalla versione 5.0, PowerShell ha una sintassi formale per definire classi e altri tipi definiti dall'utente. L'aggiunta di classi consente agli sviluppatori e ai professionisti IT di adottare PowerShell per un'ampia gamma di casi d'uso.

Una dichiarazione di classe è un progetto usato per creare istanze di oggetti in fase di esecuzione. Quando si definisce una classe, il nome della classe è il nome del tipo. Ad esempio, se si dichiara una classe denominata Device e si inizializza una variabile $dev in una nuova istanza di Device, $dev è un oggetto o un'istanza di tipo Device. Ogni istanza di Device può avere valori diversi nelle relative proprietà.

Scenari supportati

  • Definire tipi personalizzati in PowerShell usando semantica di programmazione orientata agli oggetti, ad esempio classi, proprietà, metodi, ereditarietà e così via.
  • Definire le risorse DSC e i relativi tipi associati usando il linguaggio di PowerShell.
  • Definire attributi personalizzati per decorare variabili, parametri e definizioni di tipi personalizzati.
  • Definire eccezioni personalizzate che possono essere rilevate dal nome del tipo.

Sintassi

Sintassi della definizione

Le definizioni di classe usano la sintassi seguente:

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> ...]
}

Sintassi di creazione di istanze

Per creare un'istanza di una classe, usare una delle sintassi seguenti:

[$<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>]}

Nota

Quando si usa la [<class-name>]::new() sintassi, le parentesi quadre intorno al nome della classe sono obbligatorie. Le parentesi quadre segnalano una definizione di tipo per PowerShell.

La sintassi hashtable funziona solo per le classi con un costruttore predefinito che non prevede parametri. Crea un'istanza della classe con il costruttore predefinito e quindi assegna le coppie chiave-valore alle proprietà dell'istanza. Se una chiave nella tabella hash non è un nome di proprietà valido, PowerShell genera un errore.

Esempio

Esempio 1 - Definizione minima

In questo esempio viene illustrata la sintassi minima necessaria per creare una classe utilizzabile.

class Device {
    [string]$Brand
}

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

Esempio 2 - Classe con membri dell'istanza

In questo esempio viene definita una classe Book con diverse proprietà, costruttori e metodi. Ogni membro definito è un membro dell'istanza , non un membro statico. Le proprietà e i metodi possono essere accessibili solo tramite un'istanza creata della classe.

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))"
    }
}

Il frammento di codice seguente crea un'istanza della classe e mostra come si comporta. Dopo aver creato un'istanza della classe Book , nell'esempio vengono usati i GetReadingTime() metodi e GetPublishedAge() per scrivere un messaggio sul libro.

$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.

Esempio 3 - Classe con membri statici

La classe BookList in questo esempio si basa sulla classe Book nell'esempio 2. Anche se la classe BookList non può essere contrassegnata come statica, l'implementazione definisce solo la proprietà statica Books e un set di metodi statici per la gestione di tale proprietà.

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)
        }
    }
}

Ora che BookList è definito, il libro dell'esempio precedente può essere aggiunto all'elenco.

$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}

Il frammento di codice seguente chiama i metodi statici per la classe.

[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

Esempio 4 - Esecuzione parallela che danneggia uno spazio di esecuzione

Il ShowRunspaceId() metodo di [UnsafeClass] segnala ID thread diversi ma lo stesso ID di runspace. Infine, lo stato della sessione è danneggiato causando un errore, ad esempio 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($_)
    }
}

Nota

Questo esempio viene eseguito in un ciclo infinito. Immettere CTRL+C per arrestare l'esecuzione.

Proprietà della classe

Le proprietà sono variabili dichiarate nell'ambito della classe. Una proprietà può essere di qualsiasi tipo predefinito o di un'istanza di un'altra classe. Le classi possono avere zero o più proprietà. Le classi non hanno un numero massimo di proprietà.

Per altre informazioni, vedere about_Classes_Properties.

Metodi di classe

I metodi definiscono le azioni che una classe è in grado di eseguire. I metodi possono accettare parametri che specificano i dati di input. I metodi definiscono sempre un tipo di output. Se un metodo non restituisce alcun output, deve avere il tipo di output Void . Se un metodo non definisce in modo esplicito un tipo di output, il tipo di output del metodo è Void.

Per altre informazioni, vedere about_Classes_Methods.

Costruttori di classi

I costruttori consentono di impostare valori predefiniti e convalidare la logica dell'oggetto al momento della creazione dell'istanza della classe. I costruttori hanno lo stesso nome della classe. I costruttori potrebbero avere parametri per inizializzare i membri dei dati del nuovo oggetto.

Per altre informazioni, vedere about_Classes_Constructors.

Parola chiave nascosta

La hidden parola chiave nasconde un membro della classe. Il membro è ancora accessibile all'utente ed è disponibile in tutti gli ambiti in cui è disponibile l'oggetto. I membri nascosti sono nascosti dal cmdlet e non possono essere visualizzati usando il Get-Member completamento della scheda o IntelliSense all'esterno della definizione della classe.

La hidden parola chiave si applica solo ai membri della classe, non a una classe stessa.

I membri della classe nascosti sono:

  • Non incluso nell'output predefinito per la classe.
  • Non incluso nell'elenco Get-Member dei membri della classe restituiti dal cmdlet. Per visualizzare i membri nascosti con Get-Member, usare il parametro Force .
  • Non visualizzato nel completamento della scheda o IntelliSense, a meno che il completamento non si verifichi nella classe che definisce il membro nascosto.
  • Membri pubblici della classe. Possono essere accessibili, ereditati e modificati. Nascondere un membro non lo rende privato. Nasconde solo il membro come descritto nei punti precedenti.

Nota

Quando si nasconde qualsiasi overload per un metodo, tale metodo viene rimosso da IntelliSense, i risultati di completamento e l'output predefinito per Get-Member. Quando si nasconde qualsiasi costruttore, l'opzione new() viene rimossa da IntelliSense e dai risultati di completamento.

Per altre informazioni sulla parola chiave, vedere about_Hidden. Per altre informazioni sulle proprietà nascoste, vedere about_Classes_Properties. Per altre informazioni sui metodi nascosti, vedere about_Classes_Methods. Per altre informazioni sui costruttori nascosti, vedere about_Classes_Constructors.

Static (parola chiave)

La static parola chiave definisce una proprietà o un metodo che esiste nella classe e non richiede alcuna istanza.

Una proprietà statica è sempre disponibile, indipendente dall'istanza della classe. Una proprietà statica viene condivisa in tutte le istanze della classe. Un metodo statico è sempre disponibile. Tutte le proprietà statiche sono attive per l'intero intervallo di sessione.

La static parola chiave si applica solo ai membri della classe, non a una classe stessa.

Per altre informazioni sulle proprietà statiche, vedere about_Classes_Properties. Per altre informazioni sui metodi statici, vedere about_Classes_Methods. Per altre informazioni sui costruttori statici, vedere about_Classes_Constructors.

Ereditarietà nelle classi di PowerShell

È possibile estendere una classe creando una nuova classe che deriva da una classe esistente. La classe derivata eredita le proprietà e i metodi della classe base. È possibile aggiungere o eseguire l'override dei membri della classe di base in base in base alle esigenze.

PowerShell non supporta l'ereditarietà multipla. Le classi non possono ereditare direttamente da più classi.

Le classi possono anche ereditare dalle interfacce, che definiscono un contratto. Una classe che eredita da un'interfaccia deve implementare tale contratto. In tal caso, la classe può essere usata come qualsiasi altra classe che implementa tale interfaccia.

Per altre informazioni sulla derivazione di classi che ereditano da una classe di base o implementano interfacce, vedere about_Classes_Inheritance.

Affinità dello spazio di esecuzione

Uno spazio di esecuzione è l'ambiente operativo per i comandi richiamati da PowerShell. Questo ambiente include i comandi e i dati attualmente presenti e tutte le restrizioni relative al linguaggio attualmente applicabili.

Una classe di PowerShell è associata allo spazio di esecuzione in cui viene creata. L'uso di una classe di PowerShell in ForEach-Object -Parallel non è sicuro. Le chiamate al metodo nella classe vengono di nuovo sottoposto a marshalling nello spazio di esecuzione in cui è stato creato, che può danneggiare lo stato dello spazio di esecuzione o causare un deadlock.

Per un'illustrazione di come l'affinità dello spazio di esecuzione può causare errori, vedere l'esempio 4.

Esportazione di classi con acceleratori di tipo

Per impostazione predefinita, i moduli di PowerShell non esportano automaticamente classi ed enumerazioni definite in PowerShell. I tipi personalizzati non sono disponibili all'esterno del modulo senza chiamare un'istruzione using module .

Tuttavia, se un modulo aggiunge acceleratori di tipo, tali acceleratori di tipo sono immediatamente disponibili nella sessione dopo l'importazione del modulo da parte degli utenti.

Nota

L'aggiunta di acceleratori di tipi alla sessione usa un'API interna (non pubblica). L'uso di questa API può causare conflitti. Il modello descritto di seguito genera un errore se esiste già un acceleratore di tipi con lo stesso nome quando si importa il modulo. Rimuove anche gli acceleratori di tipo quando si rimuove il modulo dalla sessione.

Questo modello garantisce che i tipi siano disponibili in una sessione. Non influisce su IntelliSense o sul completamento durante la creazione di un file di script in VS Code. Per ottenere IntelliSense e i suggerimenti di completamento per i tipi personalizzati in VS Code, è necessario aggiungere un'istruzione using module all'inizio dello script.

Il modello seguente illustra come registrare classi ed enumerazioni di PowerShell come acceleratori di tipi in un modulo. Aggiungere il frammento di codice al modulo di script radice dopo qualsiasi definizione di tipo. Assicurarsi che la $ExportableTypes variabile contenga ognuno dei tipi che si desidera rendere disponibili agli utenti quando importano il modulo. L'altro codice non richiede alcuna modifica.

# 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()

Quando gli utenti importano il modulo, tutti i tipi aggiunti agli acceleratori di tipo per la sessione sono immediatamente disponibili per IntelliSense e il completamento. Quando il modulo viene rimosso, sono quindi gli acceleratori di tipo.

Importazione manuale di classi da un modulo di PowerShell

Import-Module e l'istruzione #requires importa solo le funzioni, gli alias e le variabili del modulo, come definito dal modulo. Le classi non vengono importate.

Se un modulo definisce classi ed enumerazioni ma non aggiunge acceleratori di tipi per tali tipi, usare un'istruzione using module per importarle.

L'istruzione using module importa classi ed enumerazioni dal modulo radice (ModuleToProcess) di un modulo script o di un modulo binario. Non importa in modo coerente le classi definite in moduli annidati o classi definite negli script con origine punto nel modulo radice. Definire le classi che si desidera rendere disponibili agli utenti esterni al modulo direttamente nel modulo radice.

Per altre informazioni sull'istruzione using , vedere about_Using.

Caricamento del codice appena modificato durante lo sviluppo

Durante lo sviluppo di un modulo di script, è comune apportare modifiche al codice e quindi caricare la nuova versione del modulo usando Import-Module con il parametro Force . Il ricaricamento del modulo funziona solo per le modifiche apportate alle funzioni nel modulo radice. Import-Module non ricarica i moduli annidati. Inoltre, non è possibile caricare le classi aggiornate.

Per assicurarsi di eseguire la versione più recente, è necessario avviare una nuova sessione. Le classi e le enumerazioni definite in PowerShell e importate con un'istruzione using non possono essere scaricate.

Un'altra pratica di sviluppo comune consiste nel separare il codice in file diversi. Se si dispone di una funzione in un file che usa classi definite in un altro modulo, è necessario usare l'istruzione using module per assicurarsi che le funzioni abbiano le definizioni di classe necessarie.

Il tipo PSReference non è supportato con i membri della classe

L'acceleratore [ref] di tipi è abbreviato per la classe PSReference . L'uso di [ref] per eseguire il cast di tipi di un membro di classe ha esito negativo in modo invisibile all'utente. Le API che usano [ref] parametri non possono essere usate con i membri della classe. La classe PSReference è stata progettata per supportare gli oggetti COM. Gli oggetti COM presentano casi in cui è necessario passare un valore in per riferimento.

Per altre informazioni, vedere Classe PSReference.

Limitazioni

Gli elenchi seguenti includono limitazioni per la definizione delle classi di PowerShell e la soluzione alternativa per tali limitazioni, se presenti.

Limitazioni generali

  • I membri della classe non possono usare PSReference come tipo.

    Soluzione alternativa: nessuna.

  • Le classi di PowerShell non possono essere scaricate o ricaricate in una sessione.

    Soluzione alternativa: avviare una nuova sessione.

  • Le classi di PowerShell definite in un modulo non vengono importate automaticamente.

    Soluzione alternativa: aggiungere i tipi definiti all'elenco di acceleratori di tipo nel modulo radice. In questo modo i tipi sono disponibili nell'importazione del modulo.

  • Le hidden parole chiave e static si applicano solo ai membri della classe, non a una definizione di classe.

    Soluzione alternativa: nessuna.

  • Le classi di PowerShell non sono sicure da usare nell'esecuzione parallela tra spazi di esecuzione. Quando si richiamano metodi in una classe, PowerShell esegue il marshalling delle chiamate allo spazio di esecuzione in cui è stata creata la classe, che può danneggiare lo stato dello spazio di esecuzione o causare un deadlock.

    Soluzione alternativa: nessuna.

Limitazioni del costruttore

  • Il concatenamento del costruttore non è implementato.

    Soluzione alternativa: definire metodi nascosti Init() e chiamarli dall'interno dei costruttori.

  • I parametri del costruttore non possono usare attributi, inclusi gli attributi di convalida.

    Soluzione alternativa: riassegnare i parametri nel corpo del costruttore con l'attributo di convalida.

  • I parametri del costruttore non possono definire valori predefiniti. I parametri sono sempre obbligatori.

    Soluzione alternativa: nessuna.

  • Se un overload di un costruttore è nascosto, anche ogni overload per il costruttore viene considerato nascosto.

    Soluzione alternativa: nessuna.

Limitazioni dei metodi

  • I parametri del metodo non possono usare attributi, inclusi gli attributi di convalida.

    Soluzione alternativa: riassegnare i parametri nel corpo del metodo con l'attributo di convalida o definire il metodo nel costruttore statico con il Update-TypeData cmdlet .

  • I parametri del metodo non possono definire valori predefiniti. I parametri sono sempre obbligatori.

    Soluzione alternativa: definire il metodo nel costruttore statico con il Update-TypeData cmdlet .

  • I metodi sono sempre pubblici, anche quando sono nascosti. Possono essere sottoposti a override quando la classe viene ereditata.

    Soluzione alternativa: nessuna.

  • Se un overload di un metodo è nascosto, anche ogni overload per tale metodo viene considerato nascosto.

    Soluzione alternativa: nessuna.

Limitazioni delle proprietà

  • Le proprietà statiche sono sempre modificabili. Le classi di PowerShell non possono definire proprietà statiche non modificabili.

    Soluzione alternativa: nessuna.

  • Le proprietà non possono usare l'attributo ValidateScript , perché gli argomenti dell'attributo della proprietà della classe devono essere costanti.

    Soluzione alternativa: definire una classe che eredita dal tipo ValidateArgumentsAttribute e usare invece tale attributo.

  • Le proprietà dichiarate direttamente non possono definire implementazioni getter e setter personalizzate.

    Soluzione alternativa: definire una proprietà nascosta e usare Update-TypeData per definire la logica getter e setter visibili.

  • Le proprietà non possono usare l'attributo Alias . L'attributo si applica solo ai parametri, ai cmdlet e alle funzioni.

    Soluzione alternativa: usare il Update-TypeData cmdlet per definire gli alias nei costruttori della classe.

  • Quando una classe PowerShell viene convertita in JSON con il cmdlet, il ConvertTo-Json codice JSON di output include tutte le proprietà nascoste e i relativi valori.

    Soluzione alternativa: nessuna

Limitazioni di ereditarietà

  • PowerShell non supporta la definizione di interfacce nel codice script.

    Soluzione alternativa: definire le interfacce in C# e fare riferimento all'assembly che definisce le interfacce.

  • Le classi di PowerShell possono ereditare solo da una classe di base.

    Soluzione alternativa: l'ereditarietà della classe è transitiva. Una classe derivata può ereditare da un'altra classe derivata per ottenere le proprietà e i metodi di una classe base.

  • Quando si eredita da una classe o un'interfaccia generica, è necessario definire il parametro di tipo per il generico. Una classe non può definirsi come parametro di tipo per una classe o un'interfaccia.

    Soluzione alternativa: per derivare da una classe o un'interfaccia di base generica, definire il tipo personalizzato in un file diverso .psm1 e usare l'istruzione per caricare il using module tipo. Non esiste alcuna soluzione alternativa per un tipo personalizzato da usare come parametro di tipo durante l'eredita da un generico.

Vedi anche