Existe uma maneira de passar por várias instruções de caso sem declarar case value:
repetidamente?
Eu sei que isso funciona:
switch (value)
{
case 1:
case 2:
case 3:
// Do some stuff
break;
case 4:
case 5:
case 6:
// Do some different stuff
break;
default:
// Default stuff
break;
}
mas eu gostaria de fazer algo assim:
switch (value)
{
case 1,2,3:
// Do something
break;
case 4,5,6:
// Do something
break;
default:
// Do the Default
break;
}
É esta sintaxe que estou pensando em um idioma diferente ou estou perdendo alguma coisa?
c#
switch-statement
theo
fonte
fonte
,
e um que não é compartilhado com nenhuma outra linguagem c-style. Isso me pareceria muito mais sujo.Respostas:
Não há sintaxe em C ++ nem C # para o segundo método que você mencionou.
Não há nada errado com o seu primeiro método. Se, no entanto, você tiver intervalos muito grandes, basta usar uma série de instruções if.
fonte
Eu acho que isso já foi respondido. No entanto, acho que você ainda pode misturar as duas opções de uma maneira sintaticamente melhor fazendo:
fonte
Essa sintaxe é da instrução de caso Visual Basic Select ... :
Você não pode usar esta sintaxe em c #. Em vez disso, você deve usar a sintaxe do seu primeiro exemplo.
fonte
No C # 7 (disponível por padrão no Visual Studio 2017 / .NET Framework 4.6.2), a comutação baseada em intervalo agora é possível com a instrução switch e ajudaria no problema do OP.
Exemplo:
Notas:
(
e)
não são necessários nawhen
condição, mas são usados neste exemplo para destacar as comparações.var
também pode ser usado no lugar deint
. Por exemplo:case var n when n >= 7:
.fonte
Você pode deixar de fora a nova linha que fornece:
mas considero esse estilo ruim.
fonte
O .NET Framework 3.5 possui intervalos:
Enumerable.Range do MSDN
você pode usá-lo com "contains" e a instrução IF, pois, como alguém disse, a instrução SWITCH usa o operador "==".
Aqui está um exemplo:
Mas acho que podemos nos divertir mais: como você não precisará dos valores de retorno e essa ação não aceita parâmetros, você pode facilmente usar ações!
O exemplo antigo com este novo método:
Como você está passando ações, não valores, você deve omitir os parênteses, é muito importante. Se você precisar de função com argumentos, basta alterar o tipo de
Action
paraAction<ParameterType>
. Se você precisar de valores de retorno, useFunc<ParameterType, ReturnType>
.No C # 3.0, não existe um Aplicativo Parcial fácil para encapsular o fato de que o parâmetro case é o mesmo, mas você cria um pequeno método auxiliar (um pouco detalhado, em inglês).
Aqui está um exemplo de como a nova declaração importada funcional é IMHO mais poderosa e elegante do que a antiga e imperativa.
fonte
int start
eint count
. Seus exemplos não funcionam da maneira como foram escritos. Você escreve como se o segundo argumento fosseint end
. Por exemplo -Enumerable.Range(11,20)
resultaria em 20 números que começam com 11, e não números de 11 a 20.Enumerable.Range(11,20).Contains(c)
é equivalente afor(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;
Se você tivesse um intervalo grande, levaria muito tempo, enquanto apenas o usasse>
e<
seria rápido e constante.MySwitchWithEnumerable
retornovoid
é um design fraco para esta situação. MOTIVO: Você converteu umif-else
em uma série de instruções independentes - que ocultam a intenção, que é que elas sejam mutuamente exclusivas - apenas umaaction
é executada. Em vez voltarbool
, com o corpoif (..) { action(); return true; } else return false;
O site chamando, em seguida, mostra a intenção:if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));
. Isto é preferível. No entanto, também não é mais uma melhoria significativa em relação à sua versão original, neste caso simples.Aqui está a solução completa em C # 7 ...
Também funciona com cordas ...
fonte
O código abaixo não funciona:
A única maneira de fazer isso é:
O código que você procura funciona no Visual Basic, onde você pode facilmente colocar intervalos ... na
none
opção daswitch
instrução ou nosif else
blocos convenientes, sugiro, em um ponto extremo, criar .dll com o Visual Basic e importar de volta para o seu projeto c #.Nota: o equivalente do comutador no Visual Basic é
Select Case
.fonte
Outra opção seria usar uma rotina. Se todos os casos 1 a 3 executarem a mesma lógica, envolva essa lógica em uma rotina e chame-a para cada caso. Sei que isso não se livra das declarações de caso, mas implementa um bom estilo e mantém a manutenção no mínimo ...
[Editar] Adicionada implementação alternativa para corresponder à pergunta original ... [/ Editar]
Alt
fonte
Uma faceta menos conhecida do switch em C # é que ele depende do operador = e, como pode ser substituído, você pode ter algo assim:
fonte
O gcc implementa uma extensão para a linguagem C para suportar intervalos seqüenciais:
Edit : Acabei de notar a tag C # na pergunta, então presumivelmente uma resposta do GCC não ajuda.
fonte
No C # 7, agora temos a correspondência de padrões para que você possa fazer algo como:
fonte
Na verdade, eu também não gosto do comando GOTO, mas está nos materiais oficiais da Microsoft e aqui estão todas as sintaxes permitidas.
Se o ponto final da lista de instruções de uma seção de opção estiver acessível, ocorrerá um erro em tempo de compilação. Isso é conhecido como regra "sem falhas". O exemplo
é válido porque nenhuma seção de chave possui um ponto final acessível. Diferentemente de C e C ++, a execução de uma seção de chave não é permitida "cair" para a próxima seção de chave e o exemplo
resulta em um erro em tempo de compilação. Quando a execução de uma seção de chave deve ser seguida pela execução de outra seção de chave, é necessário usar um caso explícito goto case ou goto default:
Múltiplas etiquetas são permitidas em uma seção de chave. O exemplo
Acredito que neste caso em particular, o GOTO pode ser usado, e é realmente a única maneira de avançar.
Fonte: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx
fonte
goto
quase sempre pode ser evitado (embora eu não o considere "terrível" aqui - ele está desempenhando um papel específico e estruturado). No seu exemplo, como você envolveu os corpos do caso em funções (uma coisa boa), o caso 0 pode se tornarCaseZero(); CaseZeroOrOne(); break;
. Não égoto
necessário.Parece que muito trabalho foi feito para encontrar maneiras de fazer com que uma das sintaxes menos usadas do C # parecesse melhor ou funcionasse melhor. Pessoalmente, acho que raramente vale a pena usar a instrução switch. Eu sugiro fortemente analisar quais dados você está testando e os resultados finais que deseja.
Digamos, por exemplo, que você deseja testar rapidamente valores em um intervalo conhecido para ver se são números primos. Você deseja evitar que seu código faça cálculos desnecessários e pode encontrar uma lista de números primos no intervalo que deseja online. Você pode usar uma instrução de comutação massiva para comparar cada valor com números primos conhecidos.
Ou você pode simplesmente criar um mapa de matriz de números primos e obter resultados imediatos:
Talvez você queira ver se um caractere em uma string é hexadecimal. Você pode usar uma declaração de chave feia e um tanto grande.
Ou você pode usar expressões regulares para testar o char ou usar a função IndexOf para procurar o char em uma sequência de letras hexadecimais conhecidas:
Digamos que você queira executar uma das três ações diferentes, dependendo de um valor que esteja no intervalo de 1 a 24. Eu sugeriria o uso de um conjunto de instruções IF. E se isso se tornar muito complexo (ou os números forem maiores, como 5 ações diferentes, dependendo de um valor no intervalo de 1 a 90), use uma enumeração para definir as ações e criar um mapa de matriz das enumerações. O valor seria então usado para indexar no mapa da matriz e obter a enumeração da ação que você deseja. Em seguida, use um pequeno conjunto de instruções IF ou uma instrução switch muito simples para processar o valor de enumeração resultante.
Além disso, o bom de um mapa de matriz que converte um intervalo de valores em ações é que ele pode ser facilmente alterado por código. Com código com fio, você não pode alterar facilmente o comportamento em tempo de execução, mas com um mapa de matriz é fácil.
fonte
Apenas para adicionar à conversa, usando o .NET 4.6.2, também pude fazer o seguinte. Testei o código e funcionou para mim.
Você também pode fazer várias instruções "OU", como abaixo:
Você também pode verificar se ele corresponde a um valor em uma matriz:
fonte
Se você tiver uma quantidade muito grande de seqüências de caracteres (ou qualquer outro tipo) fazendo a mesma coisa, recomendo o uso de uma lista de seqüências combinada com a propriedade string.Contains.
Então, se você tem uma declaração de switch grande assim:
Você pode substituí-lo por uma
if
declaração como esta:Essa escala é boa para qualquer número de casos de cadeia.
fonte
Eu acho que este é melhor em C # 7 ou acima.
Você também pode verificar o intervalo no caso de switch C #: Switch case: posso usar um intervalo em vez de um número ou se você quiser entender o básico do caso do switch C #
fonte
Para isso, você usaria uma instrução goto. Tal como:
fonte
goto
. Pior, é um uso completamente desnecessáriogoto
, pois a sintaxe original declarada pelo OP funciona. A questão era se havia uma maneira mais concisa de dar os casos alternativos. Como as pessoas responderam anos antes de você , sim, existe - se você deseja colocar os vários casos em uma linhacase 1: case 2:
e se o estilo automático do editor permitir.