SlideShare a Scribd company logo
LINQ
について
コードの品質について
 プログラミングをしてる時に遭遇する様々な問題
 変数名が適当だと何のための変数なのかわかりにくい
 ブロックのネストが深くなると読みにくい
 ローカル変数が多いと何がどうなっているか混乱しやすい
 etc…
コードの品質について
 何も意識せずにコードを書いているとついついネストは深くなってし
まいますよね
 例として、
あるカレンダーセットの中の
カレンダーの中の
予定のうち、
1日以内に作成されたものを抽出する
コードをお見せします
コードがわかりにくくなる例
class CalendarSet
{
public Calendar[] Calendars;
}
class Calendar
{
public Schedule[] Schedules;
}
class Schedule
{
public DateTime ScheduleCreatedAt;
}
このようなクラス構成だとします
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { }; <- 結果を格納するもの
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { }; <- 結果を格納するもの
foreach (var calendar in calendarSet.Calendars) <- カレンダーセットのカレンダーでループ
{
}
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { }; <- 結果を格納するもの
foreach (var calendar in calendarSet.Calendars) <- カレンダーセットのカレンダーでループ
{
foreach (var schedule in calendar.Schedules) <- カレンダーの予定でループ
{
}
}
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { }; <- 結果を格納するもの
foreach (var calendar in calendarSet.Calendars) <- カレンダーセットのカレンダーでループ
{
foreach (var schedule in calendar.Schedules) <- カレンダーの予定でループ
{
if (schedule.ScheduleCreatedAt > DateTime.Now.AddDays(-1))
{ ↑ 1日以内に作成された予定を
}
}
}
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { }; <- 結果を格納するもの
foreach (var calendar in calendarSet.Calendars) <- カレンダーセットのカレンダーでループ
{
foreach (var schedule in calendar.Schedules) <- カレンダーの予定でループ
{
if (schedule.ScheduleCreatedAt > DateTime.Now.AddDays(-1))
{ ↑ 1日以内に作成された予定を
recentlyCreatedSchedules.Add(schedule); <- 結果リストに格納
}
}
}
コードがわかりにくくなる例
CalendarSet calendarSet;
var recentlyCreatedSchedules = new List<Schedule> { };
foreach (var calendar in calendarSet.Calendars)
{
foreach (var schedule in calendar.Schedules)
{
if (schedule.ScheduleCreatedAt > DateTime.Now.AddDays(-1))
{
recentlyCreatedSchedules.Add(schedule);
}
}
}
↑ 結果を格納する一時変数が必要
ネストが深くて
理解しにくい
コードがわかりにくくなる例
 今の例をLINQを使って書きなおしてみましょう
LINQを使う場合
calendarSet.Calendars.SelectMany(c => c.Schedules.Select(s => s))
.Where(s => s.ScheduleCreatedAt > DateTime.Now.AddDays(-1));
LINQを使う場合
calendarSet.Calendars.SelectMany(c => c.Schedules.Select(s => s))
.Where(s => s.ScheduleCreatedAt > DateTime.Now.AddDays(-1));
!?!?!?!?!?
LINQを使う場合
calendarSet.Calendars.SelectMany(c => c.Schedules.Select(s => s))
.Where(s => s.ScheduleCreatedAt > DateTime.Now.AddDays(-1));
1行で書けてしまう
ネストも深くならない
余計なローカル変数もない
シンプルなコードで可読性も高い
LINQとは
 Language Integrated Query
 日本語にすると “言語に統合されたクエリ”
LINQの種類
 LINQにはいくつも種類があり、代表的なもので
 LINQ to Objects
 LINQ to SQL
 LINQ to Entities
 LINQ to XML
など
LINQ to Objects
 今回はオブジェクトを扱う LINQ to Objectsについて
 LINQ to Objectsとは
 あらゆるコレクション(IEnumerableを実装するオブジェクト)をLINQで操作可
能にする
 例えば
 条件を満たす要素を取得
 特定の値が含まれているか
 操作を加える
 ソート
 等 ができる
クエリ式とメソッド式
 LINQにはクエリ式とメソッド式の2つの記法がある
 メソッド式
 C# のメソッドと同じように”.”でチェーンして記述する方式
 var q = collection.Where(x => x > 10).Select(x => x * x);
 クエリ式
 SQLのようなクエリ構文でLINQを記述する方式
 var q = from x in collection where x > 10 select x * x;
クエリ式とメソッド式
 基本的にメソッド式を使う(一般的にも)
理由は
 クエリ式は必ず
from **** select ****
の形式になるので、Select()をしていないにも関わらずselectが必要
になり、何の処理が行われているかわかりにくい
クエリ式とメソッド式
 クエリ式にはない構文がある
 First() Single() 等
メソッド式
collection.Where(x => x > 10).Select(x => x * x).First();
クエリ式
(from x in collection where x > 10 select x * x).First();
無理やり使おうとするなら、一度クエリにしてから(カッコで囲んで)呼ぶ
クエリ式とメソッド式
 ただし、クエリ式のほうが優れている点もある
 ReactiveExtensionsを使って非同期処理を実装するとき
 複数の値を次のメソッドの引数として渡すとき
 メソッド式でも匿名型を用いることで、できないこともない
 など
が今の時点では使う機会はないので存在だけ知っていればよい
LINQの代表的なメソッド
 Select
 SelectMany
 Where
 All/Any
 OrderBy/OrderByDescending
 Contains
 Skip/SkipWhile
 Take/TakeWhile
 First/FirstOrDefault
 Concat
 ToArray/ToList
LINQの代表的なメソッド
 Select
 シーケンスの値を一様に変換する
var numbers = Enumerable.Range(1,10);
var number = numbers.Select(x => x * 2);
 数字を2倍にしたものが帰ってくる
LINQの代表的なメソッド
 ポイント
 基本的に次のメソッドには2つ以上の値を渡すことはできないが、匿名型を
使用することによって、疑似的にすることができる
LINQの代表的なメソッド
 匿名型を使って引数を次の標準クエリ演算子へ渡す
var names = new[] { "Taro" , "Jiro" , "Saburo" , "Shiro" };
names.Select((name, index) => new { Name = name, Index = index })
.Where(o => o.Name.Length == o.Index )
.Select(o => o.Name + o.Index);
1.NameとIndexを持つ匿名型のシーケンスを作成し、
2.Nameの文字数とIndexが一致するものを選択し、
3.NameとIndexを結合した文字列のシーケンスが帰ってくる
LINQの代表的なメソッド
 SelectMany
 シーケンスの各要素を1つのシーケンスに平坦化します。
var items = new[] {
new[] {1,2,3,4},
new[] {10,12,14},
new[] {20,22,24}
};
var result = items.SelectMany(item => item);
 平坦化されたシーケンス {1,2,3,4,10,12,14,20,22,24} が返ってくる
http://pro.art55.jp/?eid=1303957
LINQの代表的なメソッド
 Where
 条件に合致するものを取得する
var numbers = Enumerable.Range(1,10);
numbers.Where(x => x % 2 == 0);
 偶数の数列を取り出している
LINQの代表的なメソッド
 All/Any
全部の値/一つ以上の値 が条件を満たすかを判定する
var numbers = Enumerable.Range(1,10);
numbers.Any(x => x % 2 == 0);
numbers.All(x => x > 3);
 一つ目は偶数がシーケンスに含まれているかを判定
 二つ目はシーケンスに含まれているすべての数字が3より大きいか判定
LINQの代表的なメソッド
 OrderBy/OrderByDescending
 シーケンスをソートする
var names = new[] { "Taro" , "Jiro" , "Saburo" , "Shiro" };
var persons = names.Select((name, index) =>
new { Name = name, Age = index * 2 });
persons.OrderByDescending(p => p.Age);
 匿名型のAgeで降順でソートされた結果が返ってくる
 { Name = waguchi, Age = 6 }
 { Name = wada, Age = 4 }
 { Name = yamaguchi, Age = 2 }
 { Name = yamada, Age = 0 }
LINQの代表的なメソッド
 Contains
 シーケンスに特定の値が含まれているかを調べる
var names = new[] { "Taro" , "Jiro" , "Saburo" , "Shiro" };
bool b = names.Contains("hanako");
 namesに”hanako”が含まれているか判定
LINQの代表的なメソッド
 Skip/SkipWhile
 先頭からn個を除外/先頭から条件を満たすものを捨てる
var names = new[] { "Taro" , "Jiro" , "" , "Saburo" , "Shiro" };
names.Skip(3);
names.SkipWhile(name => name.Length <= 0);
 先頭から3要素を除外
 "Saburo" , "Shiro“
 要素の長さが0以下のものを除外
 "Taro" , "Jiro" , "Saburo" , "Shiro"
LINQの代表的なメソッド
 Take/TakeWhile
 先頭からn個の要素を取得/先頭から条件を満たすものを取得
var names = new[] { "Taro" , "Jiro" , "" , "Saburo" , "Shiro" };
names.Take(3);
names.TakeWhile(name => name.Length > 4);
 先頭から3要素を取得
 "Taro" , "Jiro" , ""
 要素の長さが4より大きいのものを取得
 "Saburo" , "Shiro"
LINQの代表的なメソッド
 First/FirstOrDefault
 シーケンスの最初の値を取得する
 FirstOrDefaultは要素が見つからない場合は既定値を返します。
var numbers = Enumerable.Range(3,10);
numbers.First();
var strings = new String[] {};
strings.FirstOrDefault();
 それぞれ
 3
 null
が返ってくる
LINQの代表的なメソッド
 Concat
 2つのシーケンスを連結する
var numbers = Enumerable.Range(1,5);
var numbers2 = Enumerable.Range(15,20);
numbers.Concat(numbers2);
 numbersとnumbers2を連結した値
 { 1 , 2 , 3 , 4 , 5 , 15 , 16 , 17 , 18 , 19 , 20 }
 が返ってくる
LINQの代表的なメソッド
 ToArray/ToList
 Array/Listに変換
var numbers = Enumerable.Range(1,10);
numbers.ToArray();
numbers.ToList();
 それぞれ
new[] {1,2,3,4,5,6,6,7,8,9,10};
new List<int> {1,2,3,4,5,6,6,7,8,9,10};
 と同じものが帰ってくる
LINQを使うときの注意点
 LINQにはListのForEach()がない
 LINQは副作用がないのでForEachは実装されていない
 forEach構文をつかうことは可能
 ToList().ForEach()はシーケンスを一度Listに変換していて、
処理が多くなり、メモリ消費量も多くなるため、使ってはいけない
var collection = new[] { 1 , 2, 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
× collection.ToArray().ForEach(i => System.Console.Write(i));
○ foreach ( var i in collection )
{ System.Console.WriteLine(i); }
LINQを使うときの注意点
 LINQのCount()は使用しない
 Countはクエリが実行されるたびに、シーケンスの要素を数えなおすため、
必要以上に処理が走ってしまう
 もし個数を数えたい場合は、一度リストにしてから数える
var collection = new[] { 1 , 2, 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
int count = collection.ToList().Length;
LINQを使う場合
先ほどの例に戻りますが
calendarSet.Calendars.SelectMany(c => c.Schedules.Select(s => s))
.Where(s => s.ScheduleCreatedAt > DateTime.Now.AddDays(-1));
各カレンダーの予定を平坦化されたものができる↑
そのなかから1日以内に作成されたものを取得してくる↑
LINQまとめ
コードの品質を高め、
生産性を上げることができます。
LINQが使える場所では
絶対に使いましょう。
おわり

More Related Content

PDF
Constexpr 中3女子テクニック
PDF
関数プログラミング入門
PDF
iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い
PDF
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
PPTX
スキトラ Spring + mybatis
PDF
マーク&スイープ勉強会
PDF
ソーシャルゲーム案件におけるDB分割のPHP実装
PPTX
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
Constexpr 中3女子テクニック
関数プログラミング入門
iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
スキトラ Spring + mybatis
マーク&スイープ勉強会
ソーシャルゲーム案件におけるDB分割のPHP実装
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜

What's hot (20)

PDF
MvcのFatモデルに立ち向かう
PDF
視線を検出したかった(第56回 コンピュータビジョン勉強会@関東)
PDF
ブラック企業から学ぶMVCモデル
PDF
20分くらいでわかった気分になれるC++20コルーチン
PDF
PHPで大規模ブラウザゲームを開発してわかったこと
ODP
MVC の Model を考える
PPTX
WinFormsからWPFへ
PDF
XcodeのTargetについてのTIPS
PDF
入社1年目のプログラミング初心者がSpringを学ぶための手引き
PPTX
Using or not using magic onion
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
PDF
ガイデットフィルタとその周辺
PDF
ゲーム開発者のための C++11/C++14
PPTX
Msを16倍出し抜くwpf開発2回目
PDF
3次元レジストレーション(PCLデモとコード付き)
PPTX
純粋関数型アルゴリズム入門
PDF
MySQL 8.0で憶えておいてほしいこと
PDF
GUI アプリケーションにおける MVC
PDF
PlaySQLAlchemy: SQLAlchemy入門
PDF
さいきんの InnoDB Adaptive Flushing (仮)
MvcのFatモデルに立ち向かう
視線を検出したかった(第56回 コンピュータビジョン勉強会@関東)
ブラック企業から学ぶMVCモデル
20分くらいでわかった気分になれるC++20コルーチン
PHPで大規模ブラウザゲームを開発してわかったこと
MVC の Model を考える
WinFormsからWPFへ
XcodeのTargetについてのTIPS
入社1年目のプログラミング初心者がSpringを学ぶための手引き
Using or not using magic onion
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
ガイデットフィルタとその周辺
ゲーム開発者のための C++11/C++14
Msを16倍出し抜くwpf開発2回目
3次元レジストレーション(PCLデモとコード付き)
純粋関数型アルゴリズム入門
MySQL 8.0で憶えておいてほしいこと
GUI アプリケーションにおける MVC
PlaySQLAlchemy: SQLAlchemy入門
さいきんの InnoDB Adaptive Flushing (仮)
Ad

Similar to C#を始めたばかりの人へのLINQ to Objects (20)

PDF
LINQソースでGO!
PPTX
LINQ概要
PPTX
Linqことはじめ
PDF
Linq To Fun
PDF
VS勉強会 .NET Framework 入門
PPTX
C# LINQ ~深く知って、使いまくろう~
PDF
Final LINQ Extensions
PPTX
Linqの速度測ってみた
PPTX
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
PPTX
LINQ 概要 + 結構便利な LINQ to XML
PPTX
LINQ の概要とかもろもろ
PDF
Reactive extensions入門v0.1
PPTX
20080201
PPTX
C# 3.0 以降
PDF
An Internal of LINQ to Objects
PDF
非.NETerに向けたLINQの紹介
PDF
MlnagoyaRx02
PDF
LINQ in Unity
PDF
MlnagoyaRx
PPTX
Visual Studio による開発環境・プログラミングの進化
LINQソースでGO!
LINQ概要
Linqことはじめ
Linq To Fun
VS勉強会 .NET Framework 入門
C# LINQ ~深く知って、使いまくろう~
Final LINQ Extensions
Linqの速度測ってみた
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
LINQ 概要 + 結構便利な LINQ to XML
LINQ の概要とかもろもろ
Reactive extensions入門v0.1
20080201
C# 3.0 以降
An Internal of LINQ to Objects
非.NETerに向けたLINQの紹介
MlnagoyaRx02
LINQ in Unity
MlnagoyaRx
Visual Studio による開発環境・プログラミングの進化
Ad

C#を始めたばかりの人へのLINQ to Objects