Pergunta

Qual destas soluções é o preferido?

Para obter uma lista:

List<ExampleInfo> exampleList = new List<ExampleInfo>();

public class ExampleInfo
{
    internal ExampleInfo()
    { }
    /* Business Properties */
    public int Id { get; set; }
    public string Type { get; set; }
    public decimal Total { get; set; }
}

Gostaria de obter subtotais baseado fora o valor 'Total'.

Opção 1:

var subtotal1 = exampleList.Where(x => x.Type == "Subtype1").Sum(x => x.Total);
var subtotal2 = exampleList.Where(x => x.Type == "Subtype2").Sum(x => x.Total);

Opção 2:

decimal subtotal1 = 0m;
decimal subtotal2 = 0m;
foreach (ExampleInfo example in exampleList)
{
    switch (example.Type)
    {
        case "Subtype1":
            subtotal1 += example.Total;
             break;
        case "Subtype2":
             subtotal2 += example.Total;
             break;
        default:
             break;

    }
}

A lista será <10 itens na maioria dos casos.

Editar: Chris levantou um ponto muito bom eu não mencionei. O programa já está usando .NET Framework 3.5 SP1 para que a compatibilidade não é uma consideração importante aqui.

Foi útil?

Solução

Ambos os exemplos têm código duplicado, e ambos não estão prontos para uma mudança na Type - que se tivesse três valores? O que se tivesse 30
Você pode usar o LINQ para grupo por ele e obter o total:

var totals = from p in exampleList
             group p by p.Type into g
             select new { Type = g.Key, Total = g.Sum(p => p.Total ) };

Assim totals é uma coleção de objetos com as propriedades Type e Total

Outras dicas

Independentemente do tamanho da lista, se você está alvejando NET 3.5 Eu iria com LINQ, se apenas para facilitar a leitura.

Eu sou um grande fã de escrever o que você quer dizer, não como ele é feito e LINQ torna isso muito fácil em tais casos.

Você provavelmente pode até mesmo puxar os cálculos em uma única instrução LINQ, agrupando por Type. Dessa forma, você não terá duas voltas para LINQ, mas apenas um, como no segundo exemplo:

var subtotals = from x in exampleList
                group x by x.Type into g
                select new { Type = x.Key, SubTotal = g.Sum(x => x.Total) };

(Não inteiramente certo se o código funciona como ele, é apenas uma adaptação rápida de um dos 101 amostras LINQ . Sintaxe deve estar ok, no entanto.)

Opção 3

var groupings = exampleList
    .GroupBy(x => x.Type, x => x.Total)
    .Select(x => new { Type = x.Key, SubTotal = x.Sum() } );

Você terá uma lista de classes assim:

class <Anonymous>
{
    public string Type { get; }    
    public decimal SubTotal { get; }  
}

enumerar e atribuir ao valor apropriado, embora possa ser um exagero para um pequeno conjunto tal.

Eu não acho que haveria muita diferença de desempenho para essas pequenas listas.

Opção 1 irá percorrer a lista duas vezes enquanto Opção 2 apenas itera através da lista uma vez. Isso pode ser mais importante para nota para listas maiores do que os pequenos.

A opção 1 é mais legível, mas eu definitivamente não deixe de fazer um comentário que itera através da lista duas vezes.

A vantagem óbvia a opção 2 é que o código funciona em .NET Framework 2.0. Usando meios LINQ que seu aplicativo requer .NET Framework 3.5.

Para option1, internamente o loop foreach será executado duas vezes pelo C # env de tempo de execução. Daí processamento tipo será mais. Mas para <10 itens, dificilmente faz alguma diferença, e a opção 1 parece mais legível. Eu iria com a opção 1 para <10 itens.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top