2013-10-10 17 views
3

Я пишу текстовое приключение для курса в консоли Visual Studio C# и решил использовать оператор switch вместо цепочки if-elses из-за того, насколько полезен случай goto (он отлично работал так далеко). Я знаю, что каждый случай внутри самого коммутатора должен быть постоянным, но мне интересно, распространяется ли это на использование случая goto. Например, у меня есть:Использование goto case (переменная); в C# switch

switch (location) 
{ 
case 1: 
    break; 
case 2: 
    break; 
case 3: 
    break; 
//I have 10 cases, each representing a location such as "Orc Cave", I just cut it down for brevity 
default: 
    break; 
} 

Я хотел бы иметь возможность вводить целочисленную переменную, а затем перейти к этому числу, я следующий, чтобы выполнить это:

string travel2 = Console.ReadLine();//inputs a integer representing each location 
int travel2A = Convert.ToInt32(travel2); 
if (1<=travel2A && travel2A<=10) 
{ 
    goto case(travel2A); 
} 
else{ 
    goto case(2);//current location 
} 

Все работает отлично еще есть это «Ожидается постоянное значение», предупреждающее о том, что это может привести к случаю (travel2A). Можно ли сделать goto case input переменной с некоторыми настройками или это просто ограничение оператора switch? Если это последний, я могу просто сделать цепочку if-elses, но, по-моему, более удобный вариант использования переменной. Любая помощь по этому поводу очень ценится! Спасибо!

+0

Вы только можете '' goto' в case' если вы находитесь внутри 'switch', который вы не используете в своем втором примере. Там у вас нет метки «2». См. Http://msdn.microsoft.com/en-us/library/13940fs2.aspx, а затем сразу увидите http://www.cs.utexas.edu/~EWD/transcriptions/EWD02xx/EWD215.html и прекратите использовать 'goto'. –

+0

Просто потому, что вы не можете использовать 'goto', не означает, что вы не можете реализовать этот проект с помощью инструкции' switch'. См. Мой ответ, чтобы обойти это. – Andrew

+0

Вы упомянули о том, что новичок в C#. Я предлагаю, чтобы после того, как ваш код работает, попробуйте отправить его на http://codereview.stackexchange.com/ для конструктивной критики. – Brian

ответ

7

Этикетки для обычного goto должны быть указаны в исходном коде. Это не выражения, которые оцениваются; они просто идентификаторы. Ярлыки для goto case должны быть постоянными выражениями, оцененными во время компиляции, а не во время выполнения.

Я бы предостерег вас от любого решения, которое в значительной степени зависит от «goto» любой формы. Существует популярный предрассудок против любого рода «goto»; gotos, как полагают, являются неэлегантными и делают ваш код трудно следовать. Существует определенная правда, лежащая в основе этого предрассудка, чтобы быть уверенным, хотя C# был тщательно разработан так, чтобы худшие злоупотребления «goto» были невозможны или маловероятны. (C# разрешает только gotos внутри одного и того же блока или от внутреннего блока до одного из его содержащихся блоков. Он никогда не позволяет перейти от внешнего блока во внутренний блок или между двумя блоками, которые не имеют отношения вложенности. Это значительно снижает вероятность «код спагетти».)

Я предполагаю, что с тех пор, как вы проходите курс, вы только начинаете изучать C#. По мере продвижения вы узнаете о методах управления потоком, которые более элегантны, чем включение случаев.

Пока мы критикуем ваш код: рассмотрим использование int.TryParse, а не Convert.ToInt32, и убедитесь, что вы обрабатываете случай, когда пользователь вводит то, что не является целым числом.

+0

Спасибо! Это только вторая неделя на C#, поэтому я все еще знаком с этим. Я перейду на то, что-нибудь для путешествия. Благодарим вас за рекомендацию int.TryParse. Я сделаю это сразу. –

+1

@ RussellDahlke: Добро пожаловать. Похоже, вы хорошо разбираетесь в контроле. Теперь сделайте шаг назад и спросите себя, можете ли вы концептуализировать свой поток более абстрактно. Текстовая приключенческая игра в основном является * автоматом *. Государственные машины имеют следующий поток: (1) создают начальное состояние, (2) принимают вход, (3) выстраивают изменение в состояние, учитывая текущее состояние и вход, (4), если новое состояние является остановкой состояние, конец программы, (5) goto 2. Если вы можете структурировать свою программу, то это может быть проще понять. Очевидно, что (3) - трудная часть! –

2

Смотрите эту POST

В основном коммутаторы не могут быть оценены заявления в случае заявления. Они должны быть подвергнуты статической оценке.

0

Как насчет:

int travel2A = Convert.ToInt32(travel2); 
if(travel2A < 1 || travel2A > 10) 
    travel2A = 2; 

switch(travel2A) { ... } 
0

Ошибка компилятора A constant value is expected говорит все это.

Причина, по которой это невозможно в C# (VB Select работает немного иначе) хорошо проявляется при запуске в режиме отладки. Всякий раз, когда вы сталкиваетесь с оператором switch, вы заметите, что код перейдет к выбранному случаю. Хотя вы получаете значительное повышение производительности, пропуская несколько сравнений, это ограничивает гибкость.

Один из способов, с которым я столкнулся в прошлом, - это рекурсия с помощью автономных методов.Поэтому вместо того, чтобы использовать goto case(travel2a), вы должны использовать вызов метода, который будет повторно вызвать оператор switch.

Action<int> foo = null; 
foo = (i) => 
{ 
    switch (i) 
    { 
     case 1: 
      Console.WriteLine("1"); 
      break; 
     case 2: 
      Console.WriteLine("1"); 
      break; 
     case 3: 
      Console.WriteLine("1"); 
      break; 
     default: 
      //goto case (i%3); 
      foo(i % 3); 
      break; 
    } 
}; 

foo(4); 
-1

Вы можете организовать case код в качестве метода и называть его просто:

switch (location) 
{ 
    case 1: 
     gocave(); 
     break; 
    case 2: 
     gocave(); 
     break; 
    case 3: 
     donotgocave(); 
     break; 
} 

или раздельным сложную логику в примитивы:

bool gocave = false; 
bool eatmushroom = false; 
switch (location) 
{ 
    case 1: 
     gocave = true; 
     break; 
    case 2: 
     gocave = true; 
     eathmushroom = true; 
     break; 
    case 3: 
     break; 
} 
if(gocave) {...} 
if(eatmushroom) {...} 
Смежные вопросы