C# Tips | コレクション・LINQ:合計算出

C# C#
スポンサーリンク

はじめに:「合計算出」は“バラバラなお金や数を一つの数字にまとめる技”

業務システムで「合計」は、ほぼ必ず出てきます。

売上合計
数量合計
工数合計

C# / LINQ では Sum を使うことで、for 文を書かずに、
「この列のここを足し合わせたい」を一行で表現できます。

ここから、初心者向けに

Sum の基本
オブジェクトのプロパティ合計
null や空コレクションとの付き合い方
GroupBy と組み合わせた「○○ごとの合計」

を順番にかみ砕いていきます。


基本:数値コレクションに対する Sum

int の合計を出す

まずは一番シンプルな例です。

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

var numbers = new List<int> { 1, 2, 3, 4, 5 };

int total = numbers.Sum();

Console.WriteLine(total); // 15
C#

Sum() は、「列のすべての要素を足し合わせた結果」を返します。

ここでの重要ポイントは、「Sum は“for で回して足していく”の省略形」だと理解することです。

int total = 0;
foreach (var n in numbers)
{
    total += n;
}
C#

これと同じことを、numbers.Sum() がやってくれています。

空コレクションのときは 0 になる

var empty = new List<int>();

int total = empty.Sum();

Console.WriteLine(total); // 0
C#

空でも例外にはならず、0 が返ってきます。
「合計 0」は自然な結果なので、この仕様はとても扱いやすいです。


オブジェクトのプロパティ合計:Sum(selector)

売上明細の金額合計を出す

業務では、単純な int のリストよりも、
「オブジェクトの中の特定のプロパティを合計したい」ことがほとんどです。

売上明細クラスを用意します。

public class Sale
{
    public string Item { get; set; } = "";
    public int Quantity { get; set; }
    public int UnitPrice { get; set; }

    public int Amount => Quantity * UnitPrice;
}
C#

データを作ります。

var sales = new List<Sale>
{
    new Sale { Item = "A", Quantity = 2, UnitPrice = 1000 }, // 2000
    new Sale { Item = "B", Quantity = 1, UnitPrice = 500 },  // 500
    new Sale { Item = "C", Quantity = 3, UnitPrice = 200 },  // 600
};
C#

金額合計を出します。

int totalAmount = sales.Sum(s => s.Amount);

Console.WriteLine(totalAmount); // 3100
C#

ここでの重要ポイントは、「Sum(s => s.Amount) の中で“何を足し合わせるか”を指定している」ことです。
Sum() は「そのまま足す」、
Sum(x => x.プロパティ) は「プロパティを取り出してから足す」というイメージです。

直接計算式を書いて合計する

プロパティを用意せずに、その場で計算しても構いません。

int totalAmount = sales.Sum(s => s.Quantity * s.UnitPrice);
C#

「数量 × 単価」を各行で計算し、それを全部足し合わせています。


null や空コレクションとの付き合い方

null かもしれないコレクションの合計

List<Sale>? sales のように、コレクション自体が null のことがあります。
そのまま sales.Sum(...) と書くと、NullReferenceException になります。

安全に書くなら、こうです。

List<Sale>? sales = GetSalesOrNull();

int totalAmount = sales?.Sum(s => s.Amount) ?? 0;

Console.WriteLine(totalAmount);
C#

sales?.Sum(...) は、sales が null のときは null を返し、
?? 0 で「null なら 0 にする」という意味になります。

ここでの重要ポイントは、「null のときの合計をどう扱うかを決める」ことです。
多くの業務では、「データなし=合計 0」とみなすのが自然です。

プロパティが null のとき

int?(null 許容 int)を合計したいこともあります。

public class WorkLog
{
    public string User { get; set; } = "";
    public int? Hours { get; set; } // null のこともある
}
C#

この場合、Sum は「null を無視して足し合わせる」動きをします。

var logs = new List<WorkLog>
{
    new WorkLog { User = "A", Hours = 5 },
    new WorkLog { User = "B", Hours = null },
    new WorkLog { User = "C", Hours = 3 },
};

int? totalHours = logs.Sum(x => x.Hours);

Console.WriteLine(totalHours); // 8
C#

ここでの重要ポイントは、「int? の Sum は戻り値も int? になる」ことです。
全部 null の場合は結果も null になるので、
「null なら 0 にしたい」なら totalHours ?? 0 のように扱います。


GroupBy と組み合わせて「○○ごとの合計」を出す

顧客ごとの売上合計

グルーピングと合計は、業務集計の鉄板コンビです。

var summary = sales
    .GroupBy(s => s.Item)
    .Select(g => new
    {
        Item  = g.Key,
        Total = g.Sum(x => x.Amount)
    });

foreach (var x in summary)
{
    Console.WriteLine($"{x.Item}: {x.Total} 円");
}
C#

ここでの重要ポイントは、「g.Sum(...) は“そのグループの中だけ”を合計している」ことです。
GroupBy で「かたまり」を作り、その中で Sum する、という流れです。

日付ごとの売上合計

日付単位の集計もよくあります。

var daily = sales
    .GroupBy(s => s.Date.Date)
    .Select(g => new
    {
        Date  = g.Key,
        Total = g.Sum(x => x.Amount)
    })
    .OrderBy(x => x.Date);
C#

「日付ごとの合計」を出し、日付順に並べています。


合計と他の集計の組み合わせ

合計と件数を一緒に出す

「合計」と「件数」はセットで使うことが多いです。

var summary = sales
    .GroupBy(s => s.Customer)
    .Select(g => new
    {
        Customer = g.Key,
        Total    = g.Sum(x => x.Amount),
        Count    = g.Count()
    });
C#

ここでの重要ポイントは、「一度グルーピングしたら、その中で Sum も Count も自由に使える」ことです。
平均を出したければ Average、最大・最小なら Max / Min も同じノリで書けます。


実務で意識してほしいこと

「何の合計か」が分かる変数名にする

total だけだと、「何の合計?」が分かりません。

totalAmount, totalQuantity, totalHours, totalSales のように、
「何を足し合わせた結果なのか」が分かる名前をつけてください。

int totalAmount   = sales.Sum(s => s.Amount);
int totalQuantity = sales.Sum(s => s.Quantity);
C#

これだけで、コードの意図がかなり読みやすくなります。

合計の前に「フィルタ」と「ソート」の順番を意識する

よくある流れは、

条件で絞る(Where)
並び順を決める(OrderBy)
合計を出す(Sum)

です。

例えば、「2026年2月の売上合計」を出したいなら、

int totalFeb = sales
    .Where(s => s.Date.Year == 2026 && s.Date.Month == 2)
    .Sum(s => s.Amount);
C#

のように、「まず対象を絞ってから合計する」という順番を意識してください。


まとめ:「合計算出ユーティリティ」は“業務の重さを数字で測るものさし”

合計算出の本質は、
「バラバラな明細を、一つの数字にギュッと圧縮して、
業務の“重さ”や“規模”を把握する」ことです。

押さえておきたいポイントは、

数値コレクションは Sum()、オブジェクトは Sum(x => x.プロパティ)
null かもしれないコレクションは ?.Sum(...) ?? 0 で扱う
int? の Sum は null を無視して足し、戻り値も int?
「○○ごとの合計」は GroupByg.Sum(...) の流れで書く

このあたりが自分の中で自然に出てくるようになると、
「for で回して手で足している」コードから卒業して、
“業務・実務で通用する LINQ ベースの集計処理”を書けるようになります。

タイトルとURLをコピーしました