1
resposta

Alternativa para o uso de Enum

Não é uma duvida, só queria compartilhar, caso algum outro aluno um dia veja esse post, a solução que eu usei ao invés de usar um Enum para a classificação indicativa do filme. Não sei se é melhor ou pior, só sei que não precisa da classe e métodos de extensão. Tudo é resolvido em um só arquivo.

Primeiro eu criei a estrutura Classificação. (Vou explicar por que eu usei um estrutura e não uma classe nos comentarios)

using System;
using System.Collections.Generic;

namespace Alura.Filmes.App.Negocio
{
    public struct Classificacao
    {
        public static readonly Classificacao Livre = new Classificacao("G");
        public static readonly Classificacao DezAnos = new Classificacao("PG");
        public static readonly Classificacao TrezeAnos = new Classificacao("PG-13");
        public static readonly Classificacao QuatorzeAnos = new Classificacao("R");
        public static readonly Classificacao DezoitoAnos = new Classificacao("NC-17");
        public static readonly Classificacao Vazio = new Classificacao();

        private static readonly Dictionary<string, Classificacao> mapa = new Dictionary<string, Classificacao>()
        {
            //Ja que pra converter pra string é só usar o metodo ToString() não vai ser preciso
            //usar o dicionario para converter de Classificacao para string.
            //Esse dicionario serve para converter de string para Classificacao, por isso as chaves são strings.
            { "G", Livre},
            { "PG", DezAnos},
            { "PG-13", TrezeAnos},
            { "R", QuatorzeAnos},
            { "NC-17", DezoitoAnos}
        };

        //O valor string predefinido no construtor.
        //Uma boa struct não deveria ter valores que mudam dentro dela, então o set
        //da propriedade é privado pra proibir que isso aconteça. Para mudar tem que
        //criar uma nova instancia da estrutura
        public string Categoria { get; private set; }


        //O construtor privado proibe a criação de uma nova instancia fora da classe.
        //O usuario é forçado a usar uma das propriedades estaticas predefinidas ou o
        //metodo GetClassificacao() para inicializar uma nova classificação
        private Classificacao(string valor = null)
        {
            Categoria = valor;
        }

        //Usado para converter um valor string vindo do banco de dados para um tipo Classificação.
        public static Classificacao GetClassificacao(string valor)
        {
            if(valor == null) //O banco de dados aceita nulo, então pode ser que o valor seja nulo.
            {
                return new Classificacao(); //A categoria vai ter o valor nulo.
            }

            if (mapa.ContainsKey(valor))
            {
                return mapa[valor];
            }
            else
            {
                throw new ArgumentException($"Não foi possivel converter o valor '{valor}' para uma classificação.");
            }
        }

        public override string ToString()
        {
            return Categoria;
        }
    }
}

Os valores estaticos no começo da classe são como as enumerações de um Enum, e podem ser acessados de um jeito muito parecido. Só chamar o nome da classe e o nome da propriedade.

Agora na classe Filme é só adicionar a propriedade string TextoClassificacao, bem parecido com o que foi feito na aula.

    public class Filme
    {
        . . .

        public string TextoClassificacao { get; private set; }
        public Classificacao Classificacao
        {
            get
            {
                return Classificacao.GetClassificacao(TextoClassificacao);
            }
            set
            {
                TextoClassificacao = value.ToString();
            }
        }

        . . .
    }

As configurações são iguais as da aula.

O que eu gosto nesse método é que ao invés de usar um "numero" do Enum, nós podemos atribuir direto uma string às propriedades, facilita a leitura e é mais intuitivo. Também não precisa de arquivos diferentes e o principal, aceita valores nulos, já que essa coluna no banco aceita nulos.

Não sei se é um método mais elegante que o da aula, mas achei interessante compartilhar, talvez alguém tire algum proveito desse código.

1 resposta

Estou continuando aqui porque a Alura tem limites de caracteres no post.

Por que estrutura e não classe?

Podia ser uma classe, mas a classe pode ser nula e eu não quero que a instancia de Classificacao dentro de Filme possa ser nula, apenas a string Categoria dentro de Classificacao pode ser nula. A estrutura não permite que a instancia seja nula, embora seus valores possam ser nulos caso a instancia não seja inicializada.

Também tem mais um motivo, na classe filme toda vez que nós recuperarmos a propriedade Classificacao nós vamos estar criando uma nova instancia recém convertida da string TextoClassificacao para o tipo Classificacao. A estrutura é um tipo de valor, e é gerenciada no stack, acredito que seja melhor que nesse caso as instancias sejam gerenciadas no stack do que no heap, já que existe a possibilidade de muitas instancias serem criadas quando forem requisitadas e destruidas quando não forem mais usadas. Acho que pode dar um pouquinho mais de performance em alguns casos, me corrijam se eu estiver errado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software