Desafio C#
Máquina de estados com enums
Enunciado
Modele uma máquina de estados para um pedido usando um enum EstadoPedido com os valores Novo, Processando, Enviado, Entregue, Cancelado. Implemente um método Transicionar(EstadoPedido atual, string acao) que retorna o próximo estado com base nas ações "processar", "enviar", "entregar" e "cancelar". Regras: de Novo pode processar ou cancelar; de Processando pode enviar ou cancelar; de Enviado pode entregar; Entregue e Cancelado são finais. No Main, simule uma sequência de ações e imprima cada transição.
Requisitos
- Defina o enum
EstadoPedidocom os cinco estados. - Implemente
Transicionarusandoswitchno estado atual e verifique a ação. - Ações inválidas devem retornar o mesmo estado e imprimir uma mensagem de erro.
- No
Main, parta deNovoe execute as ações: "processar", "enviar", "entregar", "cancelar" (esta última deve falhar).
Código inicial
using System;
enum EstadoPedido
{
Novo,
Processando,
Enviado,
Entregue,
Cancelado
}
class Program
{
static EstadoPedido Transicionar(EstadoPedido atual, string acao)
{
// Implemente
return atual;
}
static void Main()
{
// Simule as ações
}
}
Saída esperada
Estado inicial: Novo
Ação 'processar': Processando
Ação 'enviar': Enviado
Ação 'entregar': Entregue
Ação 'cancelar': Ação inválida para o estado Entregue. Permanece Entregue.
Ver dica
Use switch (atual) e dentro de cada caso verifique a ação com if ou switch (acao). Para estados finais, retorne o próprio estado e imprima a mensagem de erro.
Mostrar solução
using System;
enum EstadoPedido
{
Novo,
Processando,
Enviado,
Entregue,
Cancelado
}
class Program
{
static EstadoPedido Transicionar(EstadoPedido atual, string acao)
{
switch (atual)
{
case EstadoPedido.Novo:
if (acao == "processar") return EstadoPedido.Processando;
if (acao == "cancelar") return EstadoPedido.Cancelado;
break;
case EstadoPedido.Processando:
if (acao == "enviar") return EstadoPedido.Enviado;
if (acao == "cancelar") return EstadoPedido.Cancelado;
break;
case EstadoPedido.Enviado:
if (acao == "entregar") return EstadoPedido.Entregue;
break;
// Entregue e Cancelado são finais: nenhuma ação válida
}
// Se chegou aqui, a ação é inválida para o estado atual
Console.WriteLine($"Ação inválida para o estado {atual}. Permanece {atual}.");
return atual;
}
static void Main()
{
EstadoPedido estado = EstadoPedido.Novo;
Console.WriteLine($"Estado inicial: {estado}");
string[] acoes = { "processar", "enviar", "entregar", "cancelar" };
foreach (var acao in acoes)
{
estado = Transicionar(estado, acao);
Console.WriteLine($"Ação '{acao}': {estado}");
}
}
}
Passo a passo
- Definimos o enum
EstadoPedidocom os cinco estados possíveis do pedido. - O método
Transicionarrecebe o estado atual e a ação como string. - Usamos
switch (atual)para ramificar conforme o estado. ParaNovo, aceitamos "processar" e "cancelar"; paraProcessando, "enviar" e "cancelar"; paraEnviado, "entregar". - Se a ação não corresponder a nenhuma transição válida, saímos do
switche imprimimos uma mensagem de erro, retornando o estado atual. - No
Main, inicializamos comNovoe percorremos um array de ações. - A cada iteração, chamamos
Transicionare atualizamos o estado, imprimindo a transição. - A última ação "cancelar" não é válida para
Entregue, então a mensagem de erro é exibida e o estado permaneceEntregue.
Por que funciona
O enum fornece um conjunto fechado de estados, e o switch garante que todas as transições sejam tratadas de forma explícita. A verificação da ação dentro de cada caso implementa a lógica da máquina de estados. Como os estados finais (Entregue e Cancelado) não têm casos no switch, qualquer ação cai no fluxo de erro, mantendo o estado inalterado.
Erros comuns
- Esquecer de tratar estados finais: se não houver caso para
Entregue, oswitchsimplesmente não faz nada e retorna o estado atual, mas sem mensagem de erro. Nosso código imprime a mensagem após o switch. - Comparar strings com
==semStringComparison: para ações simples,==funciona, mas em cenários reais useStringComparison.OrdinalIgnoreCasepara ignorar maiúsculas/minúsculas. - Não retornar o estado atual em ação inválida: se retornar
default(EstadoPedido)(que éNovo), a máquina de estados quebra. Sempre retorneatual.
Outra forma de resolver
Usar um dicionário de transições: Dictionary<(EstadoPedido, string), EstadoPedido>. É mais escalável para muitas transições, mas menos legível para poucos casos. O switch é preferível aqui pela clareza.
Saída esperada
Estado inicial: Novo
Ação 'processar': Processando
Ação 'enviar': Enviado
Ação 'entregar': Entregue
Ação 'cancelar': Ação inválida para o estado Entregue. Permanece Entregue.