Saya sedang menulis kode ini:
private static Expression<Func<Binding, bool>> ToExpression(BindingCriterion criterion)
{
switch (criterion.ChangeAction)
{
case BindingType.Inherited:
var action = (byte)ChangeAction.Inherit;
return (x => x.Action == action);
case BindingType.ExplicitValue:
var action = (byte)ChangeAction.SetValue;
return (x => x.Action == action);
default:
// TODO: Localize errors
throw new InvalidOperationException("Invalid criterion.");
}
}
Dan terkejut menemukan kesalahan kompilasi:
Variabel lokal bernama 'tindakan' sudah didefinisikan dalam lingkup ini
Itu adalah masalah yang cukup mudah untuk diselesaikan; menyingkirkan yang kedua var
sudah cukup.
Jelas variabel yang dideklarasikan dalam case
blok memiliki ruang lingkup induk switch
, tapi saya ingin tahu mengapa ini. Mengingat bahwa C # tidak memungkinkan eksekusi jatuh melalui kasus-kasus lain (itu membutuhkan break
, return
, throw
, atau goto case
pernyataan pada akhir setiap case
blok), tampaknya cukup aneh bahwa hal itu akan memungkinkan deklarasi variabel di dalam salah satu case
untuk digunakan atau konflik dengan variabel di lain case
. Dengan kata lain variabel tampaknya jatuh melalui case
pernyataan meskipun eksekusi tidak bisa. C # bersusah payah untuk mempromosikan keterbacaan dengan melarang beberapa konstruksi bahasa lain yang membingungkan atau mudah disalahgunakan. Tapi ini sepertinya hanya menyebabkan kebingungan. Pertimbangkan skenario berikut:
Jika ingin mengubahnya menjadi ini:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);
Saya mendapatkan " Penggunaan 'tindakan' variabel lokal yang belum ditetapkan ". Ini membingungkan karena dalam setiap konstruksi lain di C # yang dapat saya pikirkan
var action = ...
akan menginisialisasi variabel, tetapi di sini hanya menyatakannya.Jika saya menukar kasus seperti ini:
case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; return (x => x.Action == action); case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action);
Saya mendapatkan " Tidak dapat menggunakan 'tindakan' variabel lokal sebelum dideklarasikan ". Jadi urutan blok kasus tampaknya penting di sini dengan cara yang tidak sepenuhnya jelas - Biasanya saya bisa menulis ini dalam urutan apa pun yang saya inginkan, tetapi karena
var
harus muncul di blok pertama di manaaction
digunakan, saya harus mengubahcase
blok demikian.Jika ingin mengubahnya menjadi ini:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;
Maka saya tidak mendapatkan kesalahan, tetapi dalam arti, sepertinya variabel diberi nilai sebelum dideklarasikan.
(Meskipun saya tidak dapat memikirkan kapan pun Anda benar-benar ingin melakukan ini - saya bahkan tidak tahugoto case
ada sebelum hari ini)
Jadi pertanyaan saya adalah, mengapa para desainer C # tidak memberikan case
ruang lingkup lokal mereka sendiri? Apakah ada alasan historis atau teknis untuk ini?
switch
sama sekali - Saya hanya ingin tahu tentang alasan di balik desain ini.
break
tidak mungkin dalam C #.
action
variabel Anda sebelumswitch
pernyataan, atau masukkan setiap case ke dalam kurungannya sendiri, dan Anda akan mendapatkan perilaku yang masuk akal.