Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Deskripsi singkat
PowerShell memiliki sistem jenis fleksibel yang membuatnya lebih mudah digunakan. Namun, Anda harus memahami cara kerjanya untuk menghindari hasil yang tidak terduga.
Deskripsi panjang
Secara bawaan, variabel PowerShell tidak terikat tipe. Anda dapat membuat variabel yang berisi instans dari satu jenis dan kemudian menetapkan nilai dari jenis lain. Selain itu, PowerShell secara otomatis mengonversi nilai ke jenis lain, baik secara eksplisit maupun implisit. Meskipun konversi jenis implisit dapat membantu, ada jebakan, terutama untuk pengguna yang lebih akrab dengan bahasa yang memiliki penanganan jenis yang lebih ketat.
Variabel yang dibatasi jenis dan konversi jenis eksplisit
Untuk membatasi jenis variabel, tempatkan jenis harfiah di sebelah kiri nama variabel dalam penugasan. Misalnya:
[int]$foo = 42
Anda dapat menggunakan pengubahan tipe untuk mengonversi nilai secara eksplisit ke jenis tertentu. Misalnya:
PS> $var = [int]'43'
PS> $var.GetType().Name
Int32
Pembatasan jenis memastikan bahwa hanya nilai dari jenis yang ditentukan yang dapat ditetapkan ke variabel. PowerShell melakukan konversi implisit jika Anda mencoba menetapkan nilai dari jenis berbeda yang dapat dikonversi ke jenis yang dibatasi. Untuk informasi lebih lanjut, lihat bagian konversi jenis implisit di artikel ini.
Konversi jenis numerik
Jenis numerik dapat dikonversi ke jenis numerik lainnya selama jenis target mampu menahan nilai yang dikonversi. Misalnya:
PS> (42.1).GetType().Name
Double
PS> $byte = [byte] 42.1
PS> $byte
42
PS> $byte.GetType().Name
Byte
Nilai 42.1
adalah Ganda. Ketika Anda mengubahnya menjadi Byte , PowerShell memotongnya menjadi bilangan bulat 42
, yang cukup kecil untuk dimasukkan ke dalam Byte .
Saat mengonversi angka riil ke jenis bilangan bulat, PowerShell menggunakan pembulatan daripada pemotongan, khususnya menggunakan metode pembulatan-ke-terdekat-genap .
Contoh berikut mengilustrasikan perilaku ini. Kedua nilai dibulatkan ke bilangan bulat genap terdekat, 22
.
PS> [byte]21.5
22
PS> [byte]22.5
22
Untuk informasi selengkapnya, lihat bagian Nilai Titik Tengah dan Konvensi Pembulatan dari metode Math.Round.
Konversi jenis Boolean
Nilai jenis apa pun dapat dipaksa menjadi Boolean.
Untuk jenis numerik,
0
dikonversi ke$false
dan nilai lainnya dikonversi ke$true
.PS> [boolean]0 False PS> [boolean]0.0 False PS> [boolean]-1 True PS> [boolean]1 True PS> [boolean]42.1 True
Untuk jenis lain, nilai null, string kosong, dan array kosong dikonversi ke
$false
.PS> [boolean]'' False PS> [boolean]@() False PS> [boolean]'Hello' True
Nilai lain, termasuk hashtable yang kosong, dikonversi menjadi
$true
. Koleksi elemen tunggal mengevaluasi ke nilai Boolean dari satu dan satu-satunya elemennya. Koleksi yang memiliki lebih dari 1 elemen selalu$true
.PS> [boolean]@(0) False PS> [boolean]@(0,0) True PS> [boolean]@{} True
Konversi jenis string
Nilai jenis apa pun dapat diubah menjadi String . Konversi default adalah memanggil metode ToString()
pada objek.
Array dikonversi menjadi string. Setiap elemen dalam array dikonversi menjadi string, satu per satu dan digabungkan ke string yang dihasilkan. Secara default, nilai yang dikonversi dipisahkan oleh spasi. Pemisah dapat diubah dengan mengatur variabel preferensi $OFS
.
PS> [string] @(1, 2, 3)
1 2 3
Untuk informasi selengkapnya tentang $OFS
, lihat about_Preference_Variables.
Nilai string tunggal dapat dikonversi ke instans jenis jika jenis mengimplementasikan metode Parse()
statis. Misalnya, [bigint]'42'
sama dengan [bigint]::Parse('42', [cultureinfo]::InvariantCulture)
. Nilai [cultureinfo]::InvariantCulture
opsional mengikat parameter jenis IFormatProvider
metode. Ini memastikan perilaku konversi yang tidak berubah oleh budaya. Tidak semua implementasi metode Parse()
memiliki parameter ini.
Nota
Konversi ke dan dari string biasanya dilakukan menggunakan budaya invarian . Budaya invarian didasarkan pada, tetapi tidak identik dengan, budaya US-English. Terutama, ia menggunakan periode (.
) sebagai tanda desimal dan tanggal pertama bulan gaya AS secara default. Namun, cmdlet biner melakukan konversi yang peka terhadap budaya selama pengikatan parameter.
Konversi jenis enum
PowerShell dapat mengonversi Enum ke atau dari instans String. Misalnya, string typecast [System.PlatformId]'Unix'
sama dengan nilai enum [System.PlatformId]::Unix
. PowerShell juga menangani enum berbasis flag dengan benar untuk nilai yang dipisahkan oleh tanda koma di dalam string atau sebagai array dari string. Pertimbangkan contoh berikut:
[System.Reflection.TypeAttributes]'Public, Abstract'
[System.Reflection.TypeAttributes]('Public', 'Abstract')
Contoh-contoh ini setara dengan ekspresi enum:
[System.Reflection.TypeAttributes]::Public -bor
[System.Reflection.TypeAttributes]::Abstract
Konversi jenis lainnya
Nilai tunggal (non-array) dapat dikonversi ke instans jenis jika:
- Jenis tersebut memiliki konstruktor parameter tunggal (publik)
- Dan nilainya memiliki jenis yang sama atau dapat diubah menjadi jenis dari parameter
Misalnya, dua baris berikut setara:
[regex]'a|b'
[regex]::new('a|b')`
Jenis implisit
PowerShell juga menetapkan jenis ke nilai harfiah secara otomatis.
Literal numerik secara implisit ditik secara default. Angka diketik berdasarkan ukuran mereka. Misalnya, [int32]::MaxValue
disimpan sebagai Int64. Meskipun
String literal secara implisit dititikkan sebagai string . Instans String karakter tunggal dapat dikonversi ke dan dari tipe Char. Namun, PowerShell tidak memiliki jenis literal Char .
Konversi jenis implisit
Dalam konteks tertentu, PowerShell dapat secara implisit mengonversi nilai ke jenis lain. Konteks ini meliputi:
- Pengikatan parameter
- Variabel yang dibatasi jenis
- Ekspresi menggunakan operator
- Konteks Boolean - PowerShell mengonversi ekspresi kondisional pernyataan
if
,while
,do
, atauswitch
menjadi nilai Boolean, seperti yang dijelaskan sebelumnya. Untuk informasi selengkapnya, lihat about_Booleans. - Definisi jenis Extended Type System (ETS) - Konversi jenis dapat ditentukan dalam beberapa cara:
- Menggunakan parameter TypeConverter
dari Update-TypeData - Dalam file tipe.ps1xml
- Dalam kode yang dikompilasi untuk jenis yang dihiasi dengan atribut TypeConverterAttribute
- Melalui kelas yang berasal dari TypeConverter atau PSTypeConverter
- Menggunakan parameter TypeConverter
Konversi pengikatan parameter
PowerShell mencoba mengonversi nilai yang diteruskan ke parameter agar sesuai dengan jenis parameter. Konversi jenis nilai parameter terjadi dalam cmdlet, fungsi, skrip, blok skrip, atau metode .NET tempat parameter dideklarasikan dengan jenis tertentu. Mendeklarasikan parameter dengan jenis [Object]
atau tidak menentukan jenis tertentu memungkinkan jenis nilai apa pun diteruskan ke parameter. Parameter juga dapat memiliki konversi kustom yang ditentukan dengan mendekorasi parameter menggunakan atribut ArgumentTransformationAttribute.
Untuk informasi selengkapnya, lihat about_Parameter_Binding.
Praktik terbaik untuk pengikatan parameter
Untuk metode .NET, lebih baik memberikan tipe yang tepat yang diharapkan dengan menggunakan pengubahan tipe jika diperlukan. Tanpa jenis yang tepat, PowerShell dapat memilih metode yang salah kelebihan beban. Selain itu, kelebihan beban metode baru yang ditambahkan dalam versi .NET yang akan datang dapat merusak kode yang ada. Untuk contoh ekstrem dari masalah ini, lihat pertanyaan Stack Overflow ini.
Jika Anda meneruskan array ke parameter [string]
yang ditik, PowerShell mungkin mengonversi array menjadi string seperti yang dijelaskan sebelumnya. Pertimbangkan fungsi dasar berikut:
function Test-String {
param([string] $String)
$String
}
Test-String -String 1, 2
Fungsi ini menghasilkan 1 2
karena array dikonversi menjadi string. Untuk menghindari perilaku ini, buat fungsi tingkat lanjut
function Test-String {
[CmdletBinding()]
param([string] $String)
$String
}
Test-String -String 1, 2
Untuk fungsi tingkat lanjut, PowerShell menolak untuk mengikat array ke jenis non-array. Saat Anda meneruskan array, PowerShell mengembalikan pesan kesalahan berikut:
Test-String:
Line |
7 | Test-String -String 1, 2
| ~~~~
| Cannot process argument transformation on parameter 'String'. Cannot
| convert value to type System.String.
Sayangnya, Anda tidak dapat menghindari perilaku ini untuk panggilan metode .NET.
PS> (Get-Date).ToString(@(1, 2))
1 2
PowerShell mengonversi array ke string
Contoh berikut menunjukkan instans lain dari masalah konversi larik.
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 memperlakukan array $bytes
sebagai daftar parameter individual meskipun $bytes
adalah array byte dan System.Guid
memiliki konstruktor Guid(byte[])
.
Pola kode umum ini adalah contoh sintaks metode semu , yang tidak selalu berfungsi seperti yang dimaksudkan. Sintaks ini diterjemahkan ke:
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".
Mengingat bahwa jenis ArgumentList adalah [Object[]]
, sebuah argumen tunggal yang kebetulan merupakan array (dari jenis apa pun) mengikat per elemen . Solusinya adalah membungkus $bytes
dalam array luar sehingga PowerShell mencari konstruktor dengan parameter yang cocok dengan konten array luar.
PS> [byte[]] $bytes = 1..16
PS> $guid = New-Object -TypeName System.Guid -ArgumentList (, $bytes)
PS> $guid
Guid
----
04030201-0605-0807-090a-0b0c0d0e0f10
Item pertama dari array yang dibungkus adalah instans [byte[]]
asli kami. Nilai tersebut cocok dengan konstruktor Guid(byte[])
.
Alternatif untuk solusi pembungkusan array adalah dengan menggunakan metode new()
statis intrinsik.
PS> [byte[]] $bytes = 1..16
PS> [System.Guid]::new($bytes) # OK
Guid
----
04030201-0605-0807-090a-0b0c0d0e0f10
Konversi variabel dengan pembatasan tipe
Saat Anda menetapkan nilai ke variabel yang dibatasi jenis, PowerShell mencoba mengonversi nilai ke jenis variabel. Jika nilai yang disediakan dapat dikonversi ke jenis variabel, penugasan berhasil.
Misalnya:
PS> [int]$foo = '43'
PS> $foo.GetType().Name
Int32
Konversi berfungsi karena string '43'
dapat dikonversi menjadi angka.
Konversi operator
PowerShell dapat secara implisit mengonversi operand dalam ekspresi untuk menghasilkan hasil yang wajar. Selain itu, beberapa operator memiliki perilaku khusus jenis.
Operasi numerik
Dalam operasi numerik, bahkan jika kedua operand adalah jenis numerik yang sama, hasilnya bisa menjadi jenis yang berbeda, karena konversi jenis otomatis untuk mengakomodasi hasilnya.
PS> [int]$a = 1
PS> [int]$b = 2
PS> $result = $a / $b
PS> $result
0.5
PS> $result.GetType().Name
Double
Meskipun kedua operand adalah bilangan bulat, hasilnya dikonversi ke Double untuk mendukung hasil pecahan. Untuk mendapatkan pembagian bilangan bulat sejati, gunakan metode statis [int]::Truncate()
atau [Math]::DivRem()
. Untuk informasi selengkapnya, lihat
Dalam aritmatika bilangan bulat, ketika hasil melebihi ukuran operand, PowerShell secara default menggunakan Double untuk hasilnya, bahkan ketika hasilnya dapat masuk ke dalam tipe Int64.
PS> $result = [int]::MaxValue + 1
PS> $result
2147483648
PS> $result.GetType().Name
Double
Jika Anda ingin hasilnya menjadi Int64, Anda dapat mengonversi tipe hasil atau operan.
PS> ([int64]([int]::MaxValue + 1)).GetType().Name
Int64
Namun, gunakan kehati-hatian saat mengonversi hasil ke tipe data tertentu. Misalnya, penyaringan tipe hasil ke tipe [decimal]
dapat menyebabkan hilangnya presisi.
Menambahkan 9223372036854780000
, yang tidak akurat.
PS> ([int64]::MaxValue + 1).GetType().Name
Double
PS> [decimal]([int64]::MaxValue + 1)
9223372036854780000
Konversi dibatasi hingga 15 digit presisi. Untuk informasi selengkapnya, lihat bagian Keterangan dari dokumentasi konstruktor Decimal(Ganda).
Untuk menghindari hilangnya presisi, gunakan akhiran D
pada literal 1
. Dengan menambahkan akhiran
PS> ([int64]::MaxValue + 1D).GetType().Name
Decimal
PS> ([int64]::MaxValue + 1D)
9223372036854775808
Untuk informasi selengkapnya tentang akhiran numerik, lihat about_Numeric_Literals.
Biasanya, operan sisi kiri (LHS) operator PowerShell menentukan jenis data yang digunakan dalam operasi. PowerShell mengonversi (memaksa) operand pada sisi kanan (RHS) ke tipe yang diperlukan.
PS> 10 - ' 9 '
1
Dalam contoh ini, operand RHS adalah string ' 9 '
, yang secara implisit dikonversi menjadi bilangan bulat sebelum operasi pengurangan. Hal yang sama berlaku untuk operator perbandingan.
PS> 10 -eq ' 10'
True
PS> 10 -eq '0xa'
True
Ada pengecualian saat menggunakan operator aritmatika (+
, -
, *
, /
) dengan operan tidak numerik.
Saat Anda menggunakan -
dan /
operand dengan string, PowerShell mengonversi kedua operan dari string menjadi angka.
PS> '10' - '2'
8
PS> '10' / '2'
5
Sebaliknya, operator +
dan *
memiliki semantik khusus string (perangkaian dan replikasi).
PS> '10' + '2'
102
PS> '10' * '2'
1010
Saat Anda menggunakan nilai Boolean
PS> $false - $true
-1
Satu pengecualian adalah perkalian (*
) dari dua boolean.
PS> $false * $true
InvalidOperation: The operation '[System.Boolean] * [System.Boolean]' is not
defined.
Untuk jenis LHS lainnya, operator aritmatika hanya berhasil jika jenis tertentu mendefinisikan operator ini melalui operator kelebihan beban.
Operasi perbandingan
Operator perbandingan, seperti -eq
, -lt
, dan -gt
, dapat membandingkan operan dari berbagai jenis. Perilaku non-string dan jenis non-primitif tergantung pada apakah jenis LHS mengimplementasikan antarmuka seperti IEquatable
dan IComparable
.
Operator perbandingan berbasis koleksi (-in
dan -contains
) melakukan per elemen -eq
perbandingan hingga kecocokan ditemukan. Ini adalah setiap elemen individu dari operand koleksi yang mendorong paksaan jenis apa pun.
PS> $true -in 'true', 'false'
True
PS> 'true', 'false' -contains $true
True
Kedua contoh mengembalikan true karena 'true' -eq $true
menghasilkan $true
.
Untuk informasi selengkapnya, lihat about_Comparison_Operators.