Я писал этот код:
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'
Это было довольно легко решить проблему; просто избавиться от второго var
сделал свое дело.
Очевидно, что переменные, объявленные в case
блоках, имеют родительскую область switch
, но мне любопытно, почему это так. Учитывая , что C # не позволяет выполнение провалиться других случаях (это требует break
, return
, throw
или goto case
заявления в конце каждого case
блока), кажется , довольно странно , что это позволило бы объявления переменных в один , 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);
Я получаю « Не могу использовать локальную переменную« действие », прежде чем она объявлена ». Таким образом, порядок использования блоков case здесь важен не совсем очевидным образом. Обычно я могу записывать их в любом порядке, который мне нужен, но поскольку он
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
вообще, не используя a - мне просто любопытно обосновать этот дизайн.
break
невозможна в C #.
action
переменную передswitch
оператором или поместите каждый случай в свои фигурные скобки, и вы получите разумное поведение.