Usando Extensions e matando IF =)

Algum tempo atraz precisei desenvolver uma função para retornar o signo de uma pessoa com base na data de nascimento.

Poderia criar um classe com um metodo que passaria uma data e receberia uma string com o Signo , mas confesso que sou muito preguiçoso =)

Então resolvi criar um Extension metodo para extender DateTime, além disso resolvi bolar uma solução que não utilizasse Ifs “só sobrou um =)” :

Para eliminar if resolvi criar um list e depois utilizar linq para pesquisar na coleção.

public static class DateObjectExtensions
    {

        class SignoMesDia
        {
            public Int16 Mes { get; set; }
            public Int16 DiaInicio { get; set; }
            public Int16 DiaFim { get; set; }
            public string Signo { get; set; }

            public SignoMesDia(Int16 _Mes, Int16 _DiaInicio, Int16 _DiaFim, string _Signo)
            {
                Mes = _Mes;
                DiaInicio = _DiaInicio;
                DiaFim = _DiaFim;
                Signo = _Signo;

            }


        }

       

        public static string ToSigno(this DateTime DataNascimento)
        {
            string signo = "Não Reconhecido";

            List<SignoMesDia> signos = new List<SignoMesDia>();

            signos.Add(new SignoMesDia(1, 1, 21, "Capricórnio"));
            signos.Add(new SignoMesDia(1, 22, 31, "Aquário"));
            signos.Add(new SignoMesDia(2, 1, 18, "Aquário"));
            signos.Add(new SignoMesDia(2, 19, 31, "Peixes"));
            signos.Add(new SignoMesDia(3, 1, 19, "Peixes"));
            signos.Add(new SignoMesDia(3, 20, 31, "Áries"));
            signos.Add(new SignoMesDia(4, 1, 20, "Áries"));
            signos.Add(new SignoMesDia(4, 21, 31, "Touro"));
            signos.Add(new SignoMesDia(5, 1, 20, "Touro"));
            signos.Add(new SignoMesDia(5, 21, 31, "Gêmeos"));
            signos.Add(new SignoMesDia(6, 1, 20, "Gêmeos"));
            signos.Add(new SignoMesDia(6, 21, 31, "Câncer"));
            signos.Add(new SignoMesDia(7, 1, 21, "Câncer"));
            signos.Add(new SignoMesDia(7, 22, 31, "Leão"));
            signos.Add(new SignoMesDia(8, 1, 22, "Leão"));
            signos.Add(new SignoMesDia(8, 23, 31, "Virgem"));
            signos.Add(new SignoMesDia(9, 1, 22, "Virgem"));
            signos.Add(new SignoMesDia(9, 23, 31, "Libra"));
            signos.Add(new SignoMesDia(10, 1, 22, "Libra"));
            signos.Add(new SignoMesDia(10, 23, 31, "Escorpião"));
            signos.Add(new SignoMesDia(11, 1, 21, "Escorpião"));
            signos.Add(new SignoMesDia(11, 22, 31, "Sagitário"));
            signos.Add(new SignoMesDia(12, 1, 21, "Sagitário"));
            signos.Add(new SignoMesDia(12, 22, 31, "Capricórnio"));




            var resposta = (from s in signos where s.Mes == DataNascimento.Month && DataNascimento.Day >= s.DiaInicio && DataNascimento.Day <= s.DiaFim select s).FirstOrDefault();

            if (resposta != null)
                signo = resposta.Signo;



            return signo;

        }}

 

 

 

Validação Genérica com Reflection X Exception

Estava dando manutenção em um código que basicamente validava 30 campos com a seguinte regra.

Se o campo for vazio passar nulo para a procedure
Senão for validar se o campo é do tipo esperado (DateTime, Numeric, etc).

Basicamente o código era igual ao abaixo para cada campo.

string valor = “20/01/01”;
DateTime? data = null;
DateTime dataTemp;

if( (!string.IsNullOrEmpty(valor)) && DateTime.TryParse(valor, out dataTemp))
{
data = new Nullable<DateTime>(dataTemp);
}

Então resolvi cria uma função genérica e fazer testes de performance, para verificar qual solução implementar na solução. Veja as opções , ambas bem extensas =)

static bool TryParseException<T>(string text, out T value)
{

value = default(T);

try
{

value = (T)Convert.ChangeType(text, typeof(T));

return true;

}

catch
{

return false;

}

}

public static bool TryParseReflection<T>(string input, out T value) where T : struct
{
var type = typeof(T);
value = default(T);
var method = type.GetMethod(
“TryParse”,
new[] { typeof(string), Type.GetType(string.Format(“{0}&”, type.FullName)) });

return (bool)method.Invoke(null, new object[] { input, value });
}

Para os campos com valores compativeis com o tipo esperado a versão com Exception foi mais rápida, claro que era esperado porque com o valor esta no formato esperado não é disparada nenhum exception. Comparativo para 30 campos (0,015 s X 0.062 s)

Agora quandos os valores não são compativeis a versão que usa Reflection é infinitamente mais rápida. Comparativo para 30 campos (0,003 s X 1.5 s)

Pelos meus testes é bem mais interessante utilizar a versão com Reflection, pois mesmo quando é mais lenta é uma diferença que um usuário não perceberá a diferença.

Claro que se você for processar milhões de registros e 99.99% for o tipo correto seja mais interessante utilizar a versão com Exception =)