Sum com Linq e valores Nullable

Vamos imaginar a seguinte situação.

Temos uma lista de produtos com nome e valor, o valor do produto pode ser nulo:

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

vamos agora tentar obter o valor total dos produtos:

List lista = db.GetProdutos();
decimal soma = lista.Sum(c => c.Valor);

Ao rodar o código, se houver um produto com valor nulo, tomamos um erro.
The cast to value type ‘Decimal’ failed because the materialized value is null. Either the result type’s generic parameter or the query must use a nullable type.
Como resolver este problema?
Para resolver é bem simples, precisamos apenas usar um comando muito útil no C# e que pouca gente conhece, o Null Coalescing (??):

decimal soma = lista.Sum(c => c.Valor ?? 0);

ou com Linq:

decimal soma = (from p in lista
              select p.Valor ?? 0).Sum();

No exemplo acima, com o ?? estou dizendo que é para retornar o Valor diferente de nulo ou 0, Semelhante ao If abaixo:
(p.Valor != null) : p.Valor ? 0

Segue abaixo um código completo mostrando o funcionamento da dica, basta criar um novo projeto Console Application e inserir o código abaixo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class Produto
    {
        public string Nome { get; set; }
        public decimal? Valor { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Produto> lista = new List<Produto>();
            lista.Add(new Produto
            {
                Nome = "Teste 1",
                Valor = (decimal)54.2
            });
            lista.Add(new Produto
            {
                Nome = "Teste 2",
                Valor = null
            });
            lista.Add(new Produto
            {
                Nome = "Teste 3",
                Valor = 65
            });

            decimal soma = (from p in lista
                            select p.Valor ?? 0).Sum();

            Console.WriteLine(soma);
            Console.ReadKey();
        }
    }
}
About these ads

Publicado em 22 de janeiro de 2012, em .NET Framework, C#, LINQ e marcado como , , , , , . Adicione o link aos favoritos. 4 Comentários.

  1. Perguntei isto outro dia ao meu instrutor e te digo com certeza que poucos conhecem, pois ele deu risada de mim quando perguntei deste conceito, mais eu nem bravejei nem nada pois sei o quanto é difícil se manter atualizado.

    Grande abraço Pedro,
    e como sempre parabens pelos posts de excelente qualidade e atualidade.

  2. aqui não deu certo, o que poderá ser?

    no VS da essa mensagem:

    Error 1 Operator ‘??’ cannot be applied to operands of type ‘decimal’ and ‘int’ C:\Sites em Desenvolvimento\EF.CasaPlacas\EF.CasaPlacas.Web\SaldoCaixa.aspx.cs 37 49 EF.CasaPlacas.Web

  3. aqui não deu certo acho que o problema pode ser que trago os valores de um edmx

    placasEntities model = new placasEntities();

    public decimal Saldo(int empresa)
    {
    DateTime data = DateTime.Now.Date;
    decimal debito = (from e in model.caixa
    where e.id_empresa == empresa && e.status.Equals(“A”) && e.dt_cadastro == data
    && e.tipo.Equals(“D”)
    select e.valor ?? 0).Sum();

    }

    Esse é o erro:

    Error 1 Operator ‘??’ cannot be applied to operands of type ‘decimal’ and ‘int’ C:\Sites em Desenvolvimento\EF.CasaPlacas\EF.CasaPlacas.Data\CaixaDao.cs 44 41 EF.CasaPlacas.Data

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

Você está comentando usando sua conta WordPress.com. Sair / Mudar )

Imagem do Twitter

Você está comentando usando sua conta Twitter. Sair / Mudar )

Foto do Facebook

Você está comentando usando sua conta Facebook. Sair / Mudar )

Conectando a %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

%d bloggers like this: