C#  - Usando os novos recursos da linguagem na prática - I


 Neste artigo vou mostrar como usar alguns dos novos recursos da linguagem C# na prática : Usando o operador condicional nulo.

Muitas vezes nos acomodamos com uma determinada prática e deixamos de evoluir por pura preguiça. Isso é tanto mais verdadeiro quando se atua na área de TI que é muito dinâmica.

Como desenvolvedores ao utilizarmos uma linguagem, ela se torna a nossa ferramenta de trabalho, e, quanto melhor a dominarmos, e quanto mais proveito tirarmos dessa ferramenta, mais eficientes seremos em nosso trabalho.

Para mostrar como podemos fazer isso usando a linguagem C# vou apresentar situações mais comuns onde podemos tirar melhor proveito da linguagem usando recursos que muitas vezes esquecemos que existem.

Situação Solução
Evitar acessar propriedades com referências nulas Utilizar o operador null condicional (?)
Simplificar a definição de propriedades Usar propriedades implementadas automaticamente
Simplificar a composição de strings Utilizar a interpolação de strings
Criar objetos e definir suas propriedades em uma única etapa Usar os inicializadores de objetos e/ou coleções
Adicionar funcionalidades a uma classe que não pode ser modificada Usar métodos de extensão
Simplificar o uso de delegates e métodos de instrução única Usar Expressões lambdas
Utilizar o recurso da tipagem implicita Usar a palavra-chave var
Crir objetos sem definir um tipo Utilizar tipos anônimos
Simplificar o uso de métodos assíncronos Utilizar as palavras-chave ascyn e await
Obter o nome do método de uma classe ou propriedade sem definir uma string estática Usar e expressão nameof

Preparando o ambiente

Para poder aplicar os recursos da linguagem C# vou criar um projeto ASP .NET MVC 5 bem simples e durante o seu desenvolvimento vamos em cada situação aplicando o recurso adequado.

Inicie o VS 2015 Community e clique em New Project;

Clique em Visual C# e no template Web e selecione ASP .NET Web Application (.NET Framework);

Clique no botão OK;

Selecione o template MVC , sem autenticação nem hospedagem na nuvem e clique em OK;

Será criado o projeto ASP .NET MVC Contendo a estrutura como mostrada abaixo:

Podemos começar a criar nossa aplicação.

Definindo o Model

Vamos definir o nosso modelo de domínio criando uma classe chamada Produto na pasta Models.

Selecione a pasta Models e no menu Project clique em Add Class informando o nome Produto e o código abaixo:

 public class Produto
    {
        public string Nome { get; set; }
        public decimal? Preco { get; set; }

        public static Produto[] GetProdutos()
        {
            Produto Tablet = new Produto
            {
                Nome = "Tablet",
                Preco = 275.99M
            };
            Produto FonesOuvido = new Produto
            {
                Nome = "Fones de Ouvido",
                Preco = 18.55M
            };

            return new Produto[] { Tablet, FonesOuvido, null };
        }
    }

Na classe Produto definimos as propriedades Nome e Preco e um método estático GetProdutos() que retorna uma array de Produtos, onde um dos produtos retornados foi definido como null.

Criando o Controller e a View e usando o operador null condicional (?)

Vamos criar um controller bem simples na pasta Controllers do projeto chamado ProdutoController.

Clique com o botão direito do mouse sobre a pasta Controllers e a seguir em Add-> Controller;

Selecione o template MVC5 Controller Empty e informe o nome ProdutoController.

Para poder executar o projeto apenas pressionando F5, altere o arquivo RouteConfig.cs na pasta App_Start conforme o código abaixo:

 public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Produto", action = "Index", id = UrlParameter.Optional }
            );
        }
    }

A seguir vamos incluir o código abaixo no arquivo ProdutoController e vamos iniciar a aplicação dos recursos da linguagem C#.

1- Usando o operador Condicional Nulo

using Mvc_CSharp.Models;
using System.Collections.Generic;

using System.Web.Mvc;

namespace Mvc_CSharp.Controllers
{
    public class ProdutoController : Controller
    {
         public ActionResult Index()
        {
            List<string> resultado = new List<string>();
            foreach (Produto p in Produto.GetProdutos())
            {

                string nome = p?.Nome;
                decimal? preco =
p?.Preco;

                resultado.Add(string.Format("Nome: {0}, Preço: {1}", nome, preco));
            }

            return View(resultado);
        }
    }
}

A forma tradicional de tratar com nulls requer uma verificação explícita, o que pode levar a um código verboso e sujeito a erros quando temos que inspecionar um objeto e suas propriedades.

O operador condicional nulo permite que os valores null sejam detectados de forma mais elegante e simples.

O método estático GetProdutos retorna um array de objetos que estamos inspecionando no método Index do controlador para obter uma lista de nomes e preços.

O problema é que tanto o objeto no array como o valor das propriedades podem ser nulos o que significa que não podemos apenas referenciar p.Nome ou p.Preco dentro do laço foreach sem correr o risco de obter uma exceção do tipo NullReferenceException.

Para evitar isso estou usando o operador condicional nulo que é um recurso novo da linguagem C# :

                string nome = p?.Nome;
                decimal? preco =
p?.Preco;
 

O operador null condicional é identificado por um sinal de interrogação ( ? ).

 - Se p é null, então o nome também será definido como null.
 - Se p não for null então o nome será definido para o valor da propriedade Produto.Nome.

O mesmo vale para a propriedade Preco.

Note que a variável que você atribui quando usa o operador condicional nulo precisa ser capaz de receber um null foi por isso que a propriedade Preco esta declarada como do tipo nullable (decimal?).

A forma tradicional de realizar a verificação seria algo assim:

      if( p!=null && p.Nome!=null)
      {
         nome = p.Nome;
      }
     else
     {
         nome = null;
     }

Usando o novo recurso simplificamos o código.

Mas podemos ir além...

2- Encadeando o uso do operador condicional nulo

Podemos encadear o uso do operador condicional nulo para navegar através de uma hierarquia de objetos e isso torna ainda mais evidente o poder deste recurso.

Vamos alterar a classe Produto criando a propriedade Acessorios de forma a criar uma referência aninhada e uma hierarquia de objeto mais complexa:

public class Produto
    {
        public string Nome { get; set; }
        public decimal? Preco { get; set; }
        public Produto Acessorios { get; set; }

        public static Produto[] GetProdutos()
        {
            Produto Tablet = new Produto
            {
                Nome = "Tablet",
                Preco = 275.99M
            };

            Produto FonesOuvido = new Produto
            {
                Nome = "Fones de Ouvido",
                Preco = 18.55M
            };

            Tablet.Acessorios = FonesOuvido;

            return new Produto[] { Tablet, FonesOuvido, null };
        }
    }

 

Agora cada objeto Produto possui a propriedade Acessorios que pode sre referenciada para cada objeto Produto.

No método GetProdutos() foi definido a propriedade Acessorios para o objeto Produto FonesOuvido.

Veja como deve ficar o código do controlador agora usando o operador condicional nulo encadeado para navegar pelas proriedades do objeto sem causar uma exceção:

using Mvc_CSharp.Models;
using System.Collections.Generic;

using System.Web.Mvc;

namespace Mvc_CSharp.Controllers
{
    public class ProdutoController : Controller
    {
         public ActionResult Index()
        {
            List<string> resultado = new List<string>();
            foreach (Produto p in Produto.GetProdutos())
            {

                string nome = p?.Nome;
                decimal? preco =
p?.Preco;
              
 string nomeAcessorio = p?.Acessorios?.Nome;

                resultado.Add(string.Format("Nome: {0}, Preço: {1}, Acessórios: {2}", nome, preco, nomeAcessorio));

            }

            return View(resultado);
        }
    }
}

Observe que aplicamos o recurso a cada parte da cadeia de propriedades :    string nomeAcessorio = p?.Acessorios?.Nome;

Neste código se Acessorios for null a propriedade Nome será atribuida com o valor null.

Vamos gerar a view para esse controlador para ver o resultado.

Clique com o botão direito sobre o controlador e a seguir clique em Add View;

Selecione o template Empty conforme mostrado a seguir e clique no botão Add:

A seguir defina o código abaixo na view Index.cshtml :

@model IEnumerable<string>

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Produtos</title>
</head>
<body>
    <ul>
        @foreach (string s in Model)
        {
            <li>@s</li>
        }
    </ul>
</body>
</html>

Executando o projeto iremos obter o seguinte resultado:

Note que a variável nomeAcessorio será null quando p for null ou quando p.Acessorios for null.

      string nomeAcessorio = p?.Acessorios?.Nome;

Caso contrário a variável terá o seu valor atribuído com o valor da propriedade p.Acessorios

3- Combinando o uso do operador condicional nulo com o operador coalescente nulo

Podemos ainda combinar o operador null condicional (?) com o operador de coalescência nulo (??) para definir um valor de retorno para apresentar valores nulos usados na aplicação.

Apenas para recordar o conceito, o operador ?? , chamado de operador de coalescência nulo, retorna o operador à esquerda se o operando não for nulo, e, retorna o operando da direita caso o seu valor for null.  Da mesma forma que o operador de coalêscencia, ele verifica por valores null antes de acessar o membro de uma instância.

Assim no trecho de código abaixo:

int? x = null;
int y = x ?? 2

O valor atribuido a y será igual a 2.

Veja como podemos combinar esses dois operadores em nosso exemplo:

using Mvc_CSharp.Models;
using System.Collections.Generic;
using System.Web.Mvc;

namespace Mvc_CSharp.Controllers
{
    public class ProdutoController : Controller
    {
        // GET: Produto
        public ActionResult Index()
        {
            List<string> resultado = new List<string>();
            foreach (Produto p in Produto.GetProdutos())
            {
                string nome = p?.Nome ?? "<Sem Nome>";
                decimal? preco = p?.Preco
?? 0;
                string nomeAcessorio = p?.Acessorios?.Nome
?? "<Sem Nome>";

                resultado.Add(string.Format("Nome: {0}, Preço: {1}, Acessórios: {2}", nome, preco, nomeAcessorio));
            }

            return View(resultado);
        }
    }
}

O operador condicional nulo garante que eu não obtenha uma exceção do tipo NullReferenceException ao navegar através das propriedades do objeto e o operador coalescente nulo garante que eu não inclua valores nulos nos resultados apresentados no navegador.

Executando o projeto novamente agora teremos o seguinte resultado:

Na próxima parte do artigo vamos continuar usando alguns dos novos recursos da linguagem C# em nossa aplicação.

Pegue o projeto aqui : Mvc_CSharp1.zip (sem as referências)

(Disse Jesus) "Quem ama a sua vida perdê-la-á, e quem neste mundo odeia a sua vida, guardá-la-á para a vida eterna."
João 12:25

 

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

Referências:


José Carlos Macoratti