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 EstadoPedido com os cinco estados.
  • Implemente Transicionar usando switch no 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 de Novo e 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

  1. Definimos o enum EstadoPedido com os cinco estados possíveis do pedido.
  2. O método Transicionar recebe o estado atual e a ação como string.
  3. Usamos switch (atual) para ramificar conforme o estado. Para Novo, aceitamos "processar" e "cancelar"; para Processando, "enviar" e "cancelar"; para Enviado, "entregar".
  4. Se a ação não corresponder a nenhuma transição válida, saímos do switch e imprimimos uma mensagem de erro, retornando o estado atual.
  5. No Main, inicializamos com Novo e percorremos um array de ações.
  6. A cada iteração, chamamos Transicionar e atualizamos o estado, imprimindo a transição.
  7. A última ação "cancelar" não é válida para Entregue, então a mensagem de erro é exibida e o estado permanece Entregue.

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, o switch simplesmente 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 == sem StringComparison: para ações simples, == funciona, mas em cenários reais use StringComparison.OrdinalIgnoreCase para 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 retorne atual.

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.