C# プログラミング すぐに現場で使える知識

Chapter 3 p.52

クエリ式と展開式。
そもそも展開式という名前で良いのかな?
クエリ式のほうが見やすいね。

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

namespace Genba.Part1
{
    public class Chapter3
    {
        public static void Run()
        {
            Part3From();
            Console.WriteLine();
            Part3OrderBy();
            Console.WriteLine();
            Part3Let();
            Console.WriteLine();
            Part3Join();
        }

        private static void Part3From()
        {
            var nums = new int[] { 1, 2, 3, 4, 5 };
            var objects = new object[] { 1, 2, 3, 4, 5 };

            var q1 =
                from int x in objects
                from y in nums
                select new { x, y };

            var q2 = objects
                .Cast<int>()
                .SelectMany(x => nums, (x, y) => new { x, y });

            Console.WriteLine("From");
            Cw(q1, q2);
        }

        public static void Part3OrderBy()
        {
            var data = new[] {
                new { X = 2, Y = 1 },
                new { X = 4, Y = 2 },
                new { X = 1, Y = 3 },
                new { X = 2, Y = 4 },
                new { X = 1, Y = 1 },
                new { X = 3, Y = 2 },
                new { X = 4, Y = 3 },
            };

            var q1 =
                from p in data
                orderby p.X ascending, p.Y descending
                select p;


            var q2 = data.OrderBy(p => p.X).ThenByDescending(p => p.X);

            Console.WriteLine("Order By");
            Cw(q1, q2);
        }

        private static void Part3Let()
        {
            var data = new[]
            {
                new { Quantity = 2, Price = 98 },
                new { Quantity = 3, Price = 150 },
                new { Quantity = 1, Price = 350 },
                new { Quantity = 5, Price = 105 },
            };

            var q1 =
                from x in data
                let TotalPrice = x.Quantity * x.Price
                where TotalPrice > 500
                select x;

            var q2 = data.Select(x => new
            {
                x, TotalPrice = x.Quantity * x.Price
            })
            .Where(_ => _.TotalPrice > 500)
            .Select(_ => _.x);

            Console.WriteLine("Let");
            Cw(q1, q2);
        }

        private static void Part3Join()
        {
            var items = new[]
            {
                new { Id = 1, Name = "A", GroupId = 1 },
                new { Id = 2, Name = "B", GroupId = 1 },
                new { Id = 3, Name = "C", GroupId = 2 },
            };

            var groups = new[]
            {
                new { Id = 1, Name = "グループ1" },
                new { Id = 2, Name = "グループ2" },
            };

            var subs = new[]
            {
                new { ParentId = 1, Value = 2 },
                new { ParentId = 1, Value = 3 },
                new { ParentId = 2, Value = 5 },
            };

            var q1 =
                from x in items
                join g in groups on x.GroupId equals g.Id
                join s in subs on x.Id equals s.ParentId into sub
                select new
                { 
                    x.Name, Group = g.Name, Sum = sub.Sum(s => s.Value)
                };

            var q2 = items.Join(groups, x => x.GroupId, g => g.Id, (x, g) => new { x, g })
                .GroupJoin(subs, _ => _.x.Id, s => s.ParentId, (_, sub) => new
                {
                    Name = _.x.Name, Group = _.g.Name,
                    Sum = sub.Sum(s => s.Value)
                });

            Console.WriteLine("Join");
            Cw(q1, q2);
        }

        private static void Cw(IEnumerable<object> q1, IEnumerable<object> q2)
        {
            Console.WriteLine("q1");
            foreach (var item in q1) {
                Console.WriteLine(item);
            }

            Console.WriteLine("q2");
            foreach (var item in q2) {
                Console.WriteLine(item);
            }
        }
    }
}