コレクションの集計処理
業務アプリケーションにおいて、売上の合計、テストの総得点、在庫数のカウントなど、データの「合計値」を求める処理は頻出します。
foreachループを使用して加算処理を実装することも可能ですが、C#のLINQ(Language Integrated Query)が提供するSumメソッドを使用することで、これらの集計処理を非常に簡潔かつ可読性の高いコードで記述できます。
この記事では、単純な数値配列の合計から、オブジェクトリスト内の特定プロパティの集計、さらには計算式を含んだ合計の算出方法について解説します。
1. 単純な数値配列の合計
intやdouble、decimalなどの数値型のコレクションに対して、引数なしでSum()メソッドを呼び出すと、その全要素の合計が返されます。
コード例:整数の合計
using System;
using System.Linq; // LINQを使用するために必須
public class SumBasicExample
{
public static void Main()
{
// 数値の配列
int[] scores = { 85, 90, 78, 92, 88 };
// 配列内の数値をすべて合計する
int totalScore = scores.Sum();
Console.WriteLine($"スコア一覧: {string.Join(", ", scores)}");
Console.WriteLine($"合計スコア: {totalScore}");
}
}
出力結果:
スコア一覧: 85, 90, 78, 92, 88
合計スコア: 433
2. オブジェクトリストの特定プロパティの合計
Sumメソッドの真価は、オブジェクトのコレクションを扱う際に発揮されます。 引数にラムダ式 x => x.Property を指定することで、「各要素のどの値を合計するか」を定義できます。
コード例:売上データの集計
日別の売上情報を持つクラスのリストから、売上金額(Amount)の合計を算出する例です。
using System;
using System.Collections.Generic;
using System.Linq;
// 売上データを表すレコード
public record DailySale(DateTime Date, int Amount);
public class SumObjectExample
{
public static void Main()
{
var salesData = new List<DailySale>
{
new DailySale(new DateTime(2025, 11, 1), 12000),
new DailySale(new DateTime(2025, 11, 2), 15500),
new DailySale(new DateTime(2025, 11, 3), 9800),
new DailySale(new DateTime(2025, 11, 4), 21000)
};
// 各要素の 'Amount' プロパティを合計する
int totalSales = salesData.Sum(sale => sale.Amount);
Console.WriteLine("--- 日別売上 ---");
foreach (var sale in salesData)
{
Console.WriteLine($"{sale.Date:MM/dd}: {sale.Amount:N0}円");
}
Console.WriteLine("--- 合計 ---");
Console.WriteLine($"総売上: {totalSales:N0}円");
}
}
出力結果:
--- 日別売上 ---
11/01: 12,000円
11/02: 15,500円
11/03: 9,800円
11/04: 21,000円
--- 合計 ---
総売上: 58,300円
3. 計算結果の合計(単価 × 数量)
Sumメソッドの引数(ラムダ式)には、単純なプロパティアクセスだけでなく、計算式を記述することも可能です。これにより、「単価 × 数量」のような小計を算出し、その総和(合計金額)を一度の処理で求めることができます。
コード例:ショッピングカートの合計金額
using System;
using System.Collections.Generic;
using System.Linq;
public record CartItem(string ProductName, int UnitPrice, int Quantity);
public class SumCalculationExample
{
public static void Main()
{
var cart = new List<CartItem>
{
new CartItem("Wireless Mouse", 3500, 2),
new CartItem("Keyboard", 8000, 1),
new CartItem("USB Cable", 1200, 3)
};
// 各商品について (単価 * 数量) を計算し、その結果を合計する
int grandTotal = cart.Sum(item => item.UnitPrice * item.Quantity);
Console.WriteLine("--- カート内訳 ---");
foreach (var item in cart)
{
int subTotal = item.UnitPrice * item.Quantity;
Console.WriteLine($"{item.ProductName}: {item.UnitPrice:N0}円 x {item.Quantity} = {subTotal:N0}円");
}
Console.WriteLine("--- 請求金額 ---");
Console.WriteLine($"合計: {grandTotal:N0}円");
}
}
出力結果:
--- カート内訳 ---
Wireless Mouse: 3,500円 x 2 = 7,000円
Keyboard: 8,000円 x 1 = 8,000円
USB Cable: 1,200円 x 3 = 3,600円
--- 請求金額 ---
合計: 18,600円
補足:空のリストとnull許容型
Sumメソッドを使用する際の挙動として、以下の点を押さえておく必要があります。
- コレクションが空の場合: 要素数が0の場合、
Sumメソッドは例外をスローせず、数値型の初期値である0を返します。 - null許容型(
int?など)の場合: 集計対象の値にnullが含まれている場合、その要素は計算から除外されます(0として扱われるのと同義です)。結果もint?(null許容型)として返されますが、全要素がnullまたは空の場合は0になります。
まとめ
Sumメソッドは、コレクション内のデータを集計するための強力なツールです。
collection.Sum(): 単純な数値リストの合計。collection.Sum(x => x.Prop): オブジェクトリストの特定プロパティの合計。collection.Sum(x => x.A * x.B): 計算式を適用した結果の合計。
foreachで一時変数を用意して加算するよりも、コードの意図が明確になり、バグの混入を防ぐことができます。
