Операторы C # Linq или foreach () для суммирования подмножеств? - PullRequest
6 голосов
/ 22 июня 2009

Какое из этих решений предпочтительнее?

Для списка:

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; }
}

Я хочу получить промежуточные итоги на основе значения «Итого».

Вариант 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);

Вариант 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;

    }
}

В большинстве случаев список будет <10 пунктов. </p>

Редактировать: Крис поднял очень хороший вопрос, который я не упомянул. Программа уже использует .NET Framework 3.5 с пакетом обновления 1 (SP1), поэтому совместимость здесь не важна.

Ответы [ 5 ]

5 голосов
/ 22 июня 2009

Независимо от размера списка, если вы ориентируетесь на .NET 3.5, я бы пошел с LINQ, если только для удобства чтения.

Я большой поклонник написания того, что вы имеете в виду, а не того, как это делается, и LINQ делает это очень легко в таких случаях.

Вы, возможно, даже можете объединить вычисления в один оператор LINQ, сгруппированный по типу. Таким образом, у вас не будет двух циклов для LINQ, а будет только один, как во втором примере:

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

(Не совсем уверен, работает ли код как есть, это просто быстрая адаптация к одному из 101 примеров LINQ . Синтаксис должен быть в порядке.) *

4 голосов
/ 22 июня 2009

В обоих этих примерах дублирован код, и оба не готовы к изменению Type - что если у него три значения? Что если бы у него было 30?
Вы можете использовать linq для группировки по нему и получить сумму:

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

Итак totals - это набор объектов со свойствами Type и Total

4 голосов
/ 22 июня 2009

Вариант 3

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

У вас будет список классов примерно так:

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

Перечислите и присвойте соответствующее значение, хотя оно может быть излишним для такого небольшого набора.

2 голосов
/ 22 июня 2009

Не думаю, что для таких небольших списков будет большая разница в производительности.

Вариант 1 будет повторять список дважды, тогда как вариант 2 повторяет список только один раз. Это может быть важнее для больших списков, чем для маленьких.

Вариант 1 более читабелен, но я обязательно сделаю комментарий, чтобы он дважды просматривал список.

Очевидным преимуществом варианта 2 является то, что код работает в .NET Framework 2.0. Использование LINQ означает, что вашему приложению требуется .NET Framework 3.5.

1 голос
/ 22 июня 2009

Для опции 1 внутренний цикл foreach будет выполняться дважды средой выполнения C #. Следовательно, тип обработки будет больше. Но для <10 элементов это вряд ли имеет значение, и вариант 1 кажется более читабельным Я бы выбрал вариант 1 для <10 предметов. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...