for WPF developers
Home Profile Tips 全記事一覧

Sum 拡張メソッドで合計値を算出する

(2017/03/14 10:56:37 created.)

Sum 拡張メソッドは元のシーケンスの総合計を算出します。元のシーケンスが数値型の場合は入力引数が不要となります。ただし、数値型でも int、long、float、double、decimal またはこれらの null 許容型のみ対応しており、uint など他の数値型には対応していません。

Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Linq;
  5.  
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             var numbers = Enumerable.Range(1, 10);
  11.             var sum = numbers.Sum();
  12.             Console.WriteLine(sum);
  13.  
  14.             var numbers2 = new uint[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  15.             // uint に対する Sum 拡張メソッドは用意されていないのでコンパイルできない
  16.             //var num2 = numbers2.Sum();
  17.  
  18.             Console.ReadKey();
  19.         }
  20.     }
  21. }


サンプルコードでは int 型を要素とするシーケンスの総合計を算出しています。変数 numbers2 は uint 型のシーケンスであるため、Sum 拡張メソッドが存在しません。

それでは、今度は次のように名前と年齢をプロパティとして持つ Person クラスに対して Sum 拡張メソッドを使ってみましょう。

Person.cs
  1. namespace Tips_Linq
  2. {
  3.     /// <summary>
  4.     /// 人物データを表します。
  5.     /// </summary>
  6.     public class Person
  7.     {
  8.         /// <summary>
  9.         /// 氏名を取得または設定します。
  10.         /// </summary>
  11.         public string Name { get; set; }
  12.  
  13.         /// <summary>
  14.         /// 年齢を取得または設定します。
  15.         /// </summary>
  16.         public int Age { get; set; }
  17.     }
  18. }
Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Linq;
  5.  
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             var people = new Person[]
  11.             {
  12.                 new Person() { Name = "田中 淳平", Age = 37 },
  13.                 new Person() { Name = "鈴木 ほのか", Age = 26 },
  14.                 new Person() { Name = "小池 哲司", Age = 22 },
  15.             };
  16.             var sum = people.Sum(x => x.Age);
  17.             Console.WriteLine(sum);
  18.  
  19.             var sum2 = people.Sum(x => x.Name.Length);
  20.             Console.WriteLine(sum2);
  21.  
  22.             Console.ReadKey();
  23.         }
  24.     }
  25. }


Sum 拡張メソッドの入力引数には、Sum 拡張メソッドが対応する数値型への射影をおこなうデリゲートを指定します。サンプルコードでは int 型である Age プロパティや文字列の長さに射影することでそれぞれの総合計を算出しています。

射影といえば Select 拡張メソッドですが、実は Sum 拡張メソッドの中ではこの Select 拡張メソッドを使用しています。ILSpy による逆コンパイル結果を見ると次のようになっています。したがって、どちらの書き方でもまったく同じ処理となるため、どちらでも好きな書き方をしても構いません。

ILSpy による逆コンパイル結果
  1. public static int Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
  2. {
  3.     return source.Select(selector).Sum();
  4. }