Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Kurzbeschreibung
PowerShell verfügt über ein flexibles Typsystem, das die Benutzerfreundlichkeit erhöht. Sie müssen jedoch verstehen, wie es funktioniert, um unerwartete Ergebnisse zu vermeiden.
Lange Beschreibung
Standardmäßig verfügen Variablen in PowerShell über keine Typeinschränkung. Sie können eine Variable erstellen, die eine Instanz eines Typs enthält, und später Werte eines anderen Typs zuweisen. Außerdem konvertiert PowerShell Werte automatisch in andere Typen, sowohl explizit als auch implizit. Während die implizite Typkonvertierung hilfreich sein kann, gibt es Fallstricke, insbesondere für Benutzer, die mit Sprachen vertrauter sind, die eine strengere Typbehandlung aufweisen.
Typbeschränkte Variablen und explizite Typkonvertierung
Um den Typ einer Variablen einzuschränken, platzieren Sie ein Typliteral in einer Zuweisung links neben dem Variablennamen. Zum Beispiel:
[int]$foo = 42
Sie können die Typumwandlung verwenden, um einen Wert explizit in einen bestimmten Typ zu konvertieren. Zum Beispiel:
PS> $var = [int]'43'
PS> $var.GetType().Name
Int32
Die Typbeschränkung stellt sicher, dass nur Werte des angegebenen Typs der Variablen zugewiesen werden können. PowerShell führt eine implizite Konvertierung aus, wenn Sie versuchen, einen Wert eines anderen Typs zuzuweisen, der in den eingeschränkten Typ konvertiert werden kann. Weitere Informationen finden Sie im Abschnitt Implizite Typkonvertierung dieses Artikels.
Konvertierung numerischer Typen
Numerische Typen können in einen beliebigen anderen numerischen Typ konvertiert werden, solange der Zieltyp den konvertierten Wert halten kann. Zum Beispiel:
PS> (42.1).GetType().Name
Double
PS> $byte = [byte] 42.1
PS> $byte
42
PS> $byte.GetType().Name
Byte
Der Wert 42.1 ist ein Double-Wert. Wenn Sie ihn in einen Byte-Wert umwandeln, wird er von PowerShell in die ganze Zahl 42 gekürzt, die klein genug ist, um in ein Byte zu passen.
Beim Konvertieren von reellen Zahlen in Ganzzahltypen verwendet PowerShell statt der Kürzung die Rundung, insbesondere die Methode zur Rundung auf die nächste gerade Zahl.
Die folgenden Beispiele veranschaulichen dieses Verhalten. Beide Werte werden auf die nächste gerade ganze Zahl gerundet, 22.
PS> [byte]21.5
22
PS> [byte]22.5
22
Weitere Informationen finden Sie im Abschnitt Mittelwerte und Rundungskonventionen zur Math.Round-Methode.
Boolesche Typkonvertierung
Der Wert eines beliebigen Typs kann in einen Boolean-Wert umgewandelt werden.
Bei numerischen Typen wird
0in$falsekonvertiert, und alle anderen Werte werden in$truekonvertiert.PS> [boolean]0 False PS> [boolean]0.0 False PS> [boolean]-1 True PS> [boolean]1 True PS> [boolean]42.1 TrueBei anderen Typen werden Nullwerte, leere Zeichenfolgen und leere Arrays in
$falsekonvertiert.PS> [boolean]'' False PS> [boolean]@() False PS> [boolean]'Hello' TrueAndere Werte, einschließlich leerer Hashtabellen, werden in
$truekonvertiert. Auflistungen mit einem Element werden als Boolean-Wert ihres einzigen Elements ausgewertet. Auflistungen mit mehr als einem Element sind immer$true.PS> [boolean]@(0) False PS> [boolean]@(0,0) True PS> [boolean]@{} True
Konvertierung von Zeichenfolgentypen
Der Wert eines beliebigen Typs kann in einen String-Wert umgewandelt werden. Die Standardkonvertierung besteht darin, die ToString()-Methode für das Objekt aufzurufen.
Arrays werden in Zeichenfolgen konvertiert. Jedes Element im Array wird in eine Zeichenfolge konvertiert, einzeln und mit der resultierenden Zeichenfolge verknüpft. Standardmäßig werden die konvertierten Werte durch ein Leerzeichen getrennt. Das Trennzeichen kann durch Festlegen der $OFS-Einstellungsvariablen geändert werden.
PS> [string] @(1, 2, 3)
1 2 3
Weitere Informationen zu $OFS finden Sie unter about_Preference_Variables.
Ein einzelner Zeichenfolgenwert kann in eine Instanz eines Typs konvertiert werden, wenn der Typ eine statische Parse()-Methode implementiert. Beispielsweise ist [bigint]'42' mit [bigint]::Parse('42', [cultureinfo]::InvariantCulture)identisch. Der optionale [cultureinfo]::InvariantCulture-Wert wird an einen IFormatProvider-Typparameter der Methode gebunden. Sie stellt sicher, dass die Konvertierung kulturinvariant verläuft. Nicht alle Implementierungen von Parse() Methoden weisen diesen Parameter auf.
Anmerkung
Konvertierungen in und aus Zeichenfolgen werden in der Regel unter Verwendung der invarianten Kultur ausgeführt. Die invariante Kultur basiert auf der US-English-Kultur, ist jedoch nicht mit ihr identisch. Insbesondere werden standardmäßig der Punkt (.) als Dezimaltrennzeichen und das amerikanische Datumsformat verwendet, bei dem der Monat zuerst genannt wird.
Binäre Cmdlets führen während der Parameterbindung jedoch kulturabhängige Konvertierungen aus.
Konvertierung von Enumerationstypen
PowerShell kann Enum-Typen in und aus String-Instanzen konvertieren. Beispielsweise ist die Typumwandlungs-Zeichenfolge [System.PlatformId]'Unix' identisch mit dem Enumerationswert [System.PlatformId]::Unix. PowerShell behandelt flagbasierte Enumerationen für durch Trennzeichen getrennte Werte innerhalb einer Zeichenfolge oder als Array von Zeichenfolgen ebenfalls ordnungsgemäß. Betrachten Sie die folgenden Beispiele:
[System.Reflection.TypeAttributes]'Public, Abstract'
[System.Reflection.TypeAttributes]('Public', 'Abstract')
Diese Beispiele entsprechen dem Enumerationsausdruck:
[System.Reflection.TypeAttributes]::Public -bor
[System.Reflection.TypeAttributes]::Abstract
Weitere Typkonvertierungen
Ein einzelner Wert (kein Array) kann in eine Instanz eines Typs konvertiert werden, wenn:
- Dieser Typ hat einen (öffentlichen) Konstruktor mit einem einzelnen Parameter.
- Der Wert ist vom selben Typ oder kann in den Typ des Parameters umgewandelt werden.
Die folgenden beiden Zeilen sind z. B. gleichwertig:
[regex]'a|b'
[regex]::new('a|b')`
Implizite Typen
PowerShell weist auch Literalwerten automatisch Typen zu.
Numerische Literale werden standardmäßig implizit typisiert. Zahlen werden basierend auf ihrer Größe typisiert. Beispielsweise ist 42 klein genug, um als Int32-Typ gespeichert zu werden, und 1.2 wird als Double-Typ gespeichert. Ganze Zahlen, die größer als [int32]::MaxValue sind, werden als Int64-gespeichert. Während 42 als Byte-Typ und 1.2 als Single-Typ gespeichert werden können, wird bei der impliziten Typisierung Int32 bzw. Double verwendet. Weitere Informationen finden Sie unter about_Numeric_Literals.
Literalzeichenfolgen werden implizit als String typisiert. Aus einem einzelnen Zeichen bestehende String-Instanzen können in und aus dem Char-Typ konvertiert werden. PowerShell verfügt jedoch nicht über einen literalen Char-Typ.
Implizite Typkonvertierung
In bestimmten Kontexten kann PowerShell Werte implizit in andere Typen konvertieren. Zu diesen Kontexten gehören:
- Parameterbindung
- Variablen mit Typeinschränkung
- Ausdrücke mit Operatoren
- Boolesche Kontexte: PowerShell konvertiert die bedingten Ausdrücke von
if-,while-,do- oderswitch-Anweisungen wie zuvor erläutert in Boolean-Werte. Weitere Informationen finden Sie unter about_Booleans. - EtS-Typdefinitionen (Extended Type System) – Typkonvertierungen können auf verschiedene Arten definiert werden:
- Mit dem TypeConverter-Parameter von Update-TypeData
- In Types.ps1xml-Dateien
- Im kompilierten Code für Typen, die mit einem TypeConverterAttribute-Attribut versehen sind
- Über Klassen, die von TypeConverter oder PSTypeConverter abgeleitet sind
Konvertierungen von Parameterbindungen
PowerShell versucht, an Parameter übergebene Werte zu konvertieren, um dem Parametertyp zu entsprechen. Die Typkonvertierung von Parameterwerten erfolgt in Cmdlets, Funktionen, Skripts, Skriptblocks oder .NET-Methoden, bei denen der Parameter mit einem bestimmten Typ deklariert wird. Wenn Sie einen Parameter mit dem Typ [Object] deklarieren oder keinen bestimmten Typ definieren, kann jeder Werttyp an einen Parameter übergeben werden. Für Parameter können auch benutzerdefinierte Konvertierungen definiert werden, indem die Parameter mit einem ArgumentTransformationAttribute-Attribut versehen werden.
Weitere Informationen finden Sie unter about_Parameter_Binding.
Bewährte Methoden für die Parameterbindung
Bei .NET-Methoden ist es besser, den exakten erwarteten Typ zu übergeben und bei Bedarf Typumwandlungen zu verwenden. Werden keine exakten Typen übergeben, kann PowerShell die falsche Methodenüberladung auswählen. Außerdem können in zukünftigen Versionen von .NET hinzugefügte neue Methodenüberladungen vorhandenen Code unterbrechen. Ein extremes Beispiel für dieses Problem finden Sie in dieser Stack Overflow-Frage.
Wenn Sie ein Array an einen [string] typierten Parameter übergeben, kann PowerShell das Array wie zuvor beschrieben in eine Zeichenfolge konvertieren. Betrachten Sie die folgende grundlegende Funktion:
function Test-String {
param([string] $String)
$String
}
Test-String -String 1, 2
Diese Funktion gibt 1 2 aus, da das Array in eine Zeichenfolge konvertiert wird. Um dieses Verhalten zu vermeiden, erstellen Sie eine erweiterte Funktion, indem Sie das attribut [CmdletBinding()] hinzufügen.
function Test-String {
[CmdletBinding()]
param([string] $String)
$String
}
Test-String -String 1, 2
Bei erweiterten Funktionen lehnt PowerShell die Bindung des Arrays an einen Typ ab, der kein Array ist. Wenn Sie ein Array übergeben, gibt PowerShell die folgende Fehlermeldung zurück:
Test-String:
Line |
7 | Test-String -String 1, 2
| ~~~~
| Cannot process argument transformation on parameter 'String'. Cannot
| convert value to type System.String.
Leider können Sie dieses Verhalten für .NET-Methodenaufrufe nicht vermeiden.
PS> (Get-Date).ToString(@(1, 2))
1 2
PowerShell konvertiert das Array in die Zeichenfolge "1 2", die an den Parameter Format der Methode ToString() übergeben wird.
Im Folgenden sehen Sie ein weiteres Beispiel für das Problem bei der Arraykonvertierung.
PS> $bytes = [byte[]] @(1..16)
PS> $guid = New-Object System.Guid($bytes)
New-Object: Cannot find an overload for "Guid" and the argument count: "16".
PowerShell behandelt das $bytes array als eine Liste einzelner Parameter, obwohl $bytes ein Bytearray ist und System.Guid über einen Guid(byte[]) Konstruktor verfügt.
Dieses allgemeine Codemuster ist ein Beispiel für die -Pseudomethodensyntax, die nicht immer wie vorgesehen funktioniert. Diese Syntax wird wie folgt übersetzt:
PS> [byte[]] $bytes = 1..16
PS> New-Object -TypeName System.Guid -ArgumentList $bytes
New-Object: Cannot find an overload for "Guid" and the argument count: "16".
Wenn ArgumentList vom Typ [Object[]] ist, wird ein einzelnes Argument, das ein Array (eines beliebigen Typs) ist, Element für Element daran gebunden. Die Problemumgehung besteht darin, $bytes in ein äußeres Array einzuschließen, sodass PowerShell nach einem Konstruktor mit Parametern sucht, die dem Inhalt des äußeren Arrays entsprechen.
PS> [byte[]] $bytes = 1..16
PS> $guid = New-Object -TypeName System.Guid -ArgumentList (, $bytes)
PS> $guid
Guid
----
04030201-0605-0807-090a-0b0c0d0e0f10
Das erste Element des umschlossenen Arrays ist die ursprüngliche [byte[]]-Instanz. Dieser Wert entspricht dem Guid(byte[])-Konstruktor.
Eine Alternative zur Problemumgehung durch Umschließen des Arrays besteht darin, die intrinsische statische new()-Methode zu verwenden.
PS> [byte[]] $bytes = 1..16
PS> [System.Guid]::new($bytes) # OK
Guid
----
04030201-0605-0807-090a-0b0c0d0e0f10
Konvertierungen von Variablen mit Typeinschränkung
Wenn Sie einer typgeschränkten Variablen einen Wert zuweisen, versucht PowerShell, den Wert in den Variablentyp zu konvertieren. Wenn der angegebene Wert in den Variablentyp konvertiert werden kann, wird die Zuordnung erfolgreich ausgeführt.
Zum Beispiel:
PS> [int]$foo = '43'
PS> $foo.GetType().Name
Int32
Die Konvertierung funktioniert, da die Zeichenfolge '43' in eine Zahl konvertiert werden kann.
Operatorkonvertierungen
PowerShell kann die Operanden in einem Ausdruck implizit konvertieren, um ein angemessenes Ergebnis zu erzielen. Außerdem weisen einige Operatoren typspezifische Verhaltensweisen auf.
Numerische Vorgänge
Bei numerischen Operationen kann das Ergebnis, selbst wenn beide Operanden denselben numerischen Typ haben, einen anderen Typ aufweisen, da eine automatische Typumwandlung erfolgt, um das Ergebnis korrekt darzustellen.
PS> [int]$a = 1
PS> [int]$b = 2
PS> $result = $a / $b
PS> $result
0.5
PS> $result.GetType().Name
Double
Obwohl beide Operanden ganzzahlig sind, wird das Ergebnis in einen Double-Typ umgewandelt, um das bruchteilige Ergebnis zu unterstützen. Um eine echte Ganzzahldivision zu erhalten, verwenden Sie die statische Methode [int]::Truncate() oder [Math]::DivRem(). Weitere Informationen finden Sie unter Truncate() und DivRem().
Wenn bei der Ganzzahlarithmetik das Ergebnis die Größe der Operanden überschreitet, verwendet PowerShell standardmäßig Double für die Ergebnisse, auch wenn das Ergebnis in einen Int64-Typ passen würde.
PS> $result = [int]::MaxValue + 1
PS> $result
2147483648
PS> $result.GetType().Name
Double
Wenn das Ergebnis ein Int64-Typ sein soll, können Sie den Ergebnistyp oder die Operanden umwandeln.
PS> ([int64]([int]::MaxValue + 1)).GetType().Name
Int64
Sie sollten jedoch mit Sorgfalt vorgehen, wenn Sie Ergebnisse in einen bestimmten Typ umwandeln. Beispielsweise kann das Umwandeln des Ergebnistyps in den [decimal]-Typ zu einem Genauigkeitsverlust führen.
Wenn Sie 1 zum maximalen Int64-Wert hinzufügen, erhalten Sie einen Double-Typ. Wenn Sie einen Double-Typ in einen Decimal-Typ umwandeln, lautet das Ergebnis 9223372036854780000, was ungenau ist.
PS> ([int64]::MaxValue + 1).GetType().Name
Double
PS> [decimal]([int64]::MaxValue + 1)
9223372036854780000
Die Umwandlung ist auf eine Genauigkeit von 15 Stellen begrenzt. Weitere Informationen finden Sie im Abschnitt Hinweise in der Dokumentation zum Decimal(Double)-Konstruktor.
Um einen Genauigkeitsverlust zu vermeiden, sollten Sie das D-Suffix für das 1-Literal verwenden. Wenn Sie das D-Suffix hinzufügen, wandelt PowerShell [int64]::MaxValue vor dem Hinzufügen von in einen 1D-Typ um.
PS> ([int64]::MaxValue + 1D).GetType().Name
Decimal
PS> ([int64]::MaxValue + 1D)
9223372036854775808
Weitere Informationen zu numerischen Suffixen finden Sie unter about_Numeric_Literals.
In der Regel bestimmt der linksseitige (LS) Operand der PowerShell-Operatoren den Datentyp, der in der Operation verwendet wird. PowerShell konvertiert den Operanden auf der rechten Seite (RS) in den erforderlichen Typ.
PS> 10 - ' 9 '
1
In diesem Beispiel ist der RS-Operand die Zeichenfolge ' 9 ', die vor dem Subtraktionsvorgang implizit in eine ganze Zahl konvertiert wird. Das gleiche gilt für die Vergleichsoperatoren.
PS> 10 -eq ' 10'
True
PS> 10 -eq '0xa'
True
Bei Verwendung von arithmetischen Operatoren (+, -, *, /) mit nicht numerischen Operanden gibt es Ausnahmen.
Wenn Sie die Operanden - und / mit Zeichenfolgen verwenden, wandelt PowerShell beide Operanden von Zeichenfolgen in Zahlen um.
PS> '10' - '2'
8
PS> '10' / '2'
5
Im Gegensatz dazu verfügen die Operatoren + und * über eine zeichenfolgenspezifische Semantik (Verkettung und Replikation).
PS> '10' + '2'
102
PS> '10' * '2'
1010
Wenn Sie booleschen Werte mit arithmetischen Operatoren verwenden, konvertiert PowerShell die Werte in ganze Zahlen: $true wird [int]1 und $false wird [int]0.
PS> $false - $true
-1
Die einzige Ausnahme ist die Multiplikation (*) von zwei Booleanen.
PS> $false * $true
InvalidOperation: The operation '[System.Boolean] * [System.Boolean]' is not
defined.
Bei anderen LS-Typen funktionieren arithmetische Operatoren nur, wenn diese Operatoren mithilfe der Operatorüberladung von einem Typ benutzerdefiniert festgelegt werden.
Vergleichsvorgänge
Die Vergleichsoperatoren wie -eq, -ltund -gtkönnen Operanden unterschiedlicher Typen vergleichen. Das Verhalten von Nicht-Zeichenfolgen und nicht primitiven Typen hängt davon ab, ob der LHS-Typ Schnittstellen wie IEquatable und IComparableimplementiert.
Die sammlungsbasierten Vergleichsoperatoren (-in und -contains) führen pro Element -eq Vergleiche aus, bis eine Übereinstimmung gefunden wird. Jedes einzelne Element des Auflistungsoperanden steuert die Typumwandlung.
PS> $true -in 'true', 'false'
True
PS> 'true', 'false' -contains $true
True
Beide Beispiele geben „true“ zurück, da 'true' -eq $true zu $true ausgewertet wird.
Weitere Informationen finden Sie unter about_Comparison_Operators.