Jawaban:
Powershell 7 memperkenalkan penggabungan nol asli, penetapan bersyarat null, dan operator terner di Powershell.
Penggabungan Nihil
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Penugasan Bersyarat Nihil
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Operator Ternary
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Tidak perlu Ekstensi Komunitas Powershell, Anda dapat menggunakan pernyataan Powershell if standar sebagai ungkapan:
variable = if (condition) { expr1 } else { expr2 }
Jadi untuk penggantian ekspresi C # pertama Anda dari:
var s = myval ?? "new value";
menjadi salah satu dari berikut ini (tergantung pada preferensi):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
atau tergantung pada apa yang mungkin berisi $ myval, Anda dapat menggunakan:
$s = if ($myval) { $myval } else { "new value" }
dan ekspresi C # kedua dipetakan dengan cara yang sama:
var x = myval == null ? "" : otherval;
menjadi
$x = if ($myval -eq $null) { "" } else { $otherval }
Sekarang untuk bersikap adil, ini tidak terlalu tajam, dan tidak nyaman digunakan sebagai bentuk C #.
Anda juga dapat mempertimbangkan untuk membungkusnya dalam fungsi yang sangat sederhana untuk membuatnya lebih mudah dibaca:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
atau mungkin sebagai, IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Seperti yang Anda lihat, fungsi yang sangat sederhana dapat memberi Anda sedikit kebebasan sintaks.
PEMBARUAN: Satu opsi tambahan untuk dipertimbangkan dalam campuran adalah fungsi IsTrue yang lebih umum:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Kemudian gabungkan yaitu kemampuan Powershell untuk mendeklarasikan alias yang terlihat seperti operator, Anda akan mendapatkan:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Jelas ini tidak akan menjadi selera semua orang, tetapi mungkin yang Anda cari.
Seperti yang dicatat Thomas, satu perbedaan halus lainnya antara versi C # dan di atas adalah bahwa C # melakukan hubungan arus pendek pada argumen, tetapi versi Powershell yang melibatkan fungsi / alias akan selalu mengevaluasi semua argumen. Jika ini menjadi masalah, gunakan if
bentuk ekspresi.
The variable '$myval' cannot be retrieved because it has not been set.
.
$myval = $null
sebelum melakukan pengujian, kesalahan tersebut akan hilang.
$null -ne $a
Tidak dapat menemukan referensi yang layak sekarang, tetapi merupakan praktik yang sudah berlangsung lama.
PowerShell 7 memperkenalkan banyak fitur baru dan bermigrasi dari .NET Framework ke .NET Core. Pada pertengahan 2020, itu belum sepenuhnya menggantikan versi lama PowerShell karena ketergantungan pada .NET Core, tetapi Microsoft telah mengindikasikan bahwa mereka bermaksud agar keluarga Core pada akhirnya menggantikan keluarga Framework lama. Pada saat Anda membaca ini, versi PowerShell yang kompatibel mungkin sudah diinstal sebelumnya di sistem Anda; jika tidak, lihat https://github.com/powershell/powershell .
Sesuai dokumentasi , operator berikut ini didukung langsung di PowerShell 7.0:
??
??=
... ? ... : ...
Ini berfungsi seperti yang Anda harapkan untuk penggabungan nol:
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
Karena operator terner telah diperkenalkan, berikut ini sekarang mungkin, meskipun itu tidak perlu mengingat penambahan operator penggabungan null:
$x = $a -eq $null ? $b : $a
Mulai 7.0, berikut ini juga tersedia jika PSNullConditionalOperators
fitur opsional diaktifkan , seperti yang dijelaskan di dokumen ( 1 , 2 ):
?.
?[]
Ini memiliki beberapa peringatan:
${}
jika diikuti oleh salah satu operator eksperimental karena tanda tanya diizinkan dalam nama variabel. Tidak jelas apakah hal ini akan terjadi jika / saat fitur berpindah dari status eksperimental (lihat masalah # 11379 ). Misalnya, ${x}?.Test()
menggunakan operator baru, tetapi $x?.Test()
menjalankan Test()
variabel bernama $x?
.?(
operator seperti yang Anda harapkan jika Anda berasal dari TypeScript. Berikut ini tidak akan berhasil:$x.Test?()
Versi PowerShell sebelum 7 memang memiliki operator penggabungan nol aktual, atau setidaknya operator yang mampu melakukan perilaku tersebut. Operator itu adalah -ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
Ini sedikit lebih fleksibel daripada operator penggabungan nol, karena ini membuat larik semua item bukan nol:
$items = $null, 'alpha', 5, 0, '', @(), $null, $true, $false
$instances = $items -ne $null
[string]::Join(', ', ($instances | ForEach-Object -Process { $_.GetType() }))
# Result:
System.String, System.Int32, System.Int32, System.String, System.Object[],
System.Boolean, System.Boolean
-eq
berfungsi serupa, yang berguna untuk menghitung entri nol:
($null, 'a', $null -eq $null).Length
# Result:
2
Tapi bagaimanapun, inilah kasus khas untuk mencerminkan ??
operator C # :
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Penjelasan ini didasarkan pada saran edit dari pengguna anonim. Terima kasih, siapapun Anda!
Berdasarkan urutan operasi, ini bekerja dengan urutan sebagai berikut:
,
Operator menciptakan sebuah array nilai yang akan diuji.-ne
filter Operator keluar semua item dari array yang sesuai dengan nilai tertentu - dalam hal ini, null. Hasilnya adalah larik nilai bukan nol dalam urutan yang sama seperti larik yang dibuat pada Langkah 1.[0]
digunakan untuk memilih elemen pertama dari larik yang difilter.Menyederhanakan itu:
Tidak seperti operator penggabungan null C #, setiap ekspresi yang mungkin akan dievaluasi, karena langkah pertama adalah membuat array.
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
dan jalankan ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
untuk melihat ini.
,
diutamakan begitu tinggi. Bagi siapa pun yang bingung tentang cara kerjanya, ($null, 'alpha', 1 -ne $null)[0]
sama saja dengan (($null, 'alpha', 1) -ne $null)[0]
. Nyatanya, hanya dua operator "tanda hubung" dengan prioritas lebih tinggi adalah -split
dan -join
(dan tanda hubung unary? Yaitu -4
atau -'56'
).
Ini hanya setengah jawaban untuk paruh pertama pertanyaan, jadi jawaban seperempat jika Anda mau, tetapi ada alternatif yang jauh lebih sederhana untuk operator penggabungan nol asalkan nilai default yang ingin Anda gunakan sebenarnya adalah nilai default untuk tipe tersebut :
string s = myval ?? "";
Dapat ditulis di Powershell sebagai:
([string]myval)
Atau
int d = myval ?? 0;
diterjemahkan menjadi Powershell:
([int]myval)
Saya menemukan yang pertama berguna saat memproses elemen xml yang mungkin tidak ada dan yang jika memang ada mungkin memiliki spasi kosong yang tidak diinginkan di sekelilingnya:
$name = ([string]$row.td[0]).Trim()
Cast to string melindungi elemen yang menjadi null dan mencegah risiko Trim()
kegagalan.
([string]$null)
-> ""
sepertinya "efek samping yang berguna, tetapi tidak menguntungkan" :(
$null, $null, 3 | Select -First 1
kembali
3
Jika Anda menginstal Modul Ekstensi Komunitas Powershell, maka Anda dapat menggunakan:
?? adalah alias untuk Invoke-NullCoalescing.
$s = ?? {$myval} {"New Value"}
?: adalah alias untuk Invoke-Ternary.
$x = ?: {$myval -eq $null} {""} {$otherval}
Terakhir, PowerShell 7 mendapatkan operator penugasan Null Coalescing !
PS > $null ?? "a"
a
PS > "x" ?? "y"
x
PS > $x = $null
PS > $x ??= "abc"
PS > $x
abc
PS > $x ??= "xyz"
PS > $x
abc
@($null,$null,"val1","val2",5) | select -First 1
Seringkali saya menemukan bahwa saya juga perlu memperlakukan string kosong sebagai null saat menggunakan penggabungan. Saya akhirnya menulis fungsi untuk ini, yang menggunakan solusi Zenexer untuk penggabungan untuk penggabungan nol sederhana, dan kemudian menggunakan Keith Hill untuk pemeriksaan nol atau kosong, dan menambahkannya sebagai bendera sehingga fungsi saya dapat melakukan keduanya.
Salah satu keuntungan dari fungsi ini adalah, fungsi ini juga menangani memiliki semua elemen null (atau kosong), tanpa mengeluarkan pengecualian. Ini juga dapat digunakan untuk banyak variabel input sewenang-wenang, berkat cara PowerShell menangani input array.
function Coalesce([string[]] $StringsToLookThrough, [switch]$EmptyStringAsNull) {
if ($EmptyStringAsNull.IsPresent) {
return ($StringsToLookThrough | Where-Object { $_ } | Select-Object -first 1)
} else {
return (($StringsToLookThrough -ne $null) | Select-Object -first 1)
}
}
Ini menghasilkan hasil tes berikut:
Null coallesce tests:
1 (w/o flag) - empty/null/'end' :
1 (with flag) - empty/null/'end' : end
2 (w/o flag) - empty/null :
2 (with flag) - empty/null :
3 (w/o flag) - empty/null/$false/'end' :
3 (with flag) - empty/null/$false/'end' : False
4 (w/o flag) - empty/null/"$false"/'end' :
4 (with flag) - empty/null/"$false"/'end' : False
5 (w/o flag) - empty/'false'/null/"$false"/'end':
5 (with flag) - empty/'false'/null/"$false"/'end': false
Kode tes:
Write-Host "Null coalesce tests:"
Write-Host "1 (w/o flag) - empty/null/'end' :" (Coalesce '', $null, 'end')
Write-Host "1 (with flag) - empty/null/'end' :" (Coalesce '', $null, 'end' -EmptyStringAsNull)
Write-Host "2 (w/o flag) - empty/null :" (Coalesce('', $null))
Write-Host "2 (with flag) - empty/null :" (Coalesce('', $null) -EmptyStringAsNull)
Write-Host "3 (w/o flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end')
Write-Host "3 (with flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end' -EmptyStringAsNull)
Write-Host "4 (w/o flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end')
Write-Host "4 (with flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end' -EmptyStringAsNull)
Write-Host "5 (w/o flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end')
Write-Host "5 (with flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end' -EmptyStringAsNull)
Yang paling dekat yang bisa saya dapatkan adalah: $Val = $MyVal |?? "Default Value"
Saya menerapkan operator penggabungan nol untuk hal di atas seperti ini:
function NullCoalesc {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$Default
)
if ($Value) { $Value } else { $Default }
}
Set-Alias -Name "??" -Value NullCoalesc
The operator ternary kondisional dapat diterapkan dengan cara similary.
function ConditionalTernary {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$First,
[Parameter(Position=1)]$Second
)
if ($Value) { $First } else { $Second }
}
Set-Alias -Name "?:" -Value ConditionalTernary
Dan digunakan seperti: $Val = $MyVal |?: $MyVal "Default Value"