私はこのコードを書いていました:
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.");
}
}
そして、コンパイルエラーを見つけて驚いた:
「action」という名前のローカル変数がこのスコープで既に定義されています
解決するのは非常に簡単な問題でした。2番目の要素を取り除くだけでvar
うまくいきました。
明らかに宣言された変数case
のブロックは親のスコープを持っているswitch
が、私はこれが理由として興味があります。C#は、実行が(それは他のケースを落下することはできませんことを考える必要があり break
、return
、throw
、またはgoto case
すべてのの終わりに文case
ブロック)、1内部変数宣言ができるようになるということは非常に奇妙に思えるcase
他に使用されるか、または変数と競合することがcase
。言い換えると、変数はcase
、実行できない場合でもステートメントを通り抜けるように見えます。C#は、混乱したり簡単に悪用されたりする他の言語の一部の構造を禁止することにより、読みやすさを高めるために多大な苦労をしています。しかし、これは混乱を引き起こすだけのように思えます。以下のシナリオを検討してください。
これに変更する場合:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);
「未割り当てのローカル変数「アクション」の使用」を取得します。C#の他のすべてのコンストラクトで
var action = ...
は、変数を初期化すると考えられるため、これは混乱を招きますが、ここでは単純に宣言しています。私がこのようなケースを交換した場合:
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);
「宣言される前にローカル変数 'action'を使用できません」と表示されます。したがって、ここではケースブロックの順序は完全には明らかではない方法で重要に見えます-通常、私は望む順序でこれらを書くことができますが、使用される
var
最初のブロックに現れる必要があるため、ブロックaction
を微調整case
する必要がありますそれに応じて。これに変更する場合:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;
エラーは発生しませんが、ある意味では、変数は宣言される前に値が割り当てられているように見えます。
(あなたが実際にこれをやりたいと思う時間は考えられませんが、goto case
今日まで存在することすら知りませんでした)
私の質問は、なぜC#のデザイナーがcase
ブロックに独自のローカルスコープを与えなかったのかということです。これには歴史的または技術的な理由がありますか?
switch
で、まったく使用せずにこれを書くことができます-私はこのデザインの背後にある理由に興味があります。
break
#を忘れるというよくある間違いがC#では不可能であることを確認するために意図的にそれを行ったと思います。
action
前に変数を宣言するswitch
か、各ケースを独自の中括弧に入れると、賢明な動作が得られます。