C#のLINQにチャレンジしてみよう!

C#のLINQとは?
C#のLINQとはLanguage-Integrated Queryの略で、配列変数やコレクションなどのデータ群から、条件文を指定してそれに合うデータを取り出す構文を意味します。データベースで使うSQLに似ていますが、違いもあります。
この記事ではSQLを知らない人でも理解できるようにわかりやすくご説明しますので、是非読んで役立ててください。
LINQの基本
まずは簡単な例から始めましょう。なおC#のLINQを使用するには、ソースコードの先頭にネームスペース指定の”using System.Linq;”を記述してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int[] ary = { 8, 4, 2, 9, 5, 0, 3, 1, 7, 6 };
// LINQクエリ構文
var result
= from val in ary
where val <= 5
select val;
// resultの中身を表示する
foreach (var num in result)
{
Console.Write(num + “);
}
|
これを実行すると、コンソールに以下のように表示されます。ary配列の5以下の値が抽出されていますね。
4 2 5 0 3 1
クエリ構文とメソッド構文
上のサンプルプログラムのLINQクエリ構文の説明は以下になります。
1
2
3
4
5
6
7
8
|
var result
(結果を入れるresultコレクション)
= from val in ary
(配列aryの値を1つvalに入れる)
where val <= 5
(valが5以下であれば)
select val;
(valをresultに入れる)
|
C#のLINQはSQLに似ていると言いましたが、selectを最後にするのがSQLと違います。なおサンプルのクエリ構文は以下のようなメソッド構文にすることも可能です。=>はC#特有のラムダ式の表記法ですね。
1
2
3
|
var result = ary
.Where(val => val <= 5)
.Select(val => val);
|
この記事では、ラムダ式を使用しないシンプルなクエリ構文で説明します。
匿名型でLINQを使う
C#の匿名型に対してLINQを使うと分かりやすいコードを記述できます。以下が例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 匿名型の配列
var human_table = new[]
{
new {FirstName = "太郎", SecondName = "山田", Age = 23, Sei = "male" },
new {FirstName = "花子", SecondName = "鈴木", Age = 18, Sei = "female" },
new {FirstName = "一郎", SecondName = "佐藤", Age = 41, Sei = "male" },
new {FirstName = "信介", SecondName = "阿部", Age = 32, Sei = "male" },
};
var result
= from row in human_table
where row.Sei == "male" // 男性のみ対象
orderby row.Age // 年齢で昇順にソート
select row.SecondName; // セカンドネームを選択
foreach (var name in result)
{
Console.WriteLine(name);
}
|
実行すると以下のように表示されます。
山田
阿部
佐藤
orderbyで昇順・降順のソートが可能
上のサンプルプログラムは名簿のうち男性だけをリストアップしてセカンドネームを取り出し、年齢の若い順(昇順)に並べて表示するという処理を行います。クエリ構文のorderbyで昇順にソートされます。
では降順にソートしたい場合はどうすれば良いのでしょうか。その場合は、
orderby row.Age descending
とすれば年齢の高い順(降順)に表示されます。なお昇順の場合は以下のようにしてもOKです。ascendingは省略できるということですね。
orderby row.Age ascending
intoでselect文を続ける
C#のクエリ構文はselectで終わりますが、その後にintoを追加するとさらに続けることができます。上のサンプルのクエリ文は以下のように記述しても同じ結果になります。
1
2
3
4
5
6
|
var result
= from row in human_table
where row.Sei == "male"
select row into row2 // intoでさらに続ける
orderby row2.Age
select row2.SecondName;
|
「男性をリストアップして、そのリストをさらに年齢の昇順でソートする」ということですね。この例では元のクエリより複雑になっていますが、クエリの条件が多い場合は役立つでしょう。
letでクエリの中で変数の代入が可能
letを使うとクエリ内で変数の計算と代入ができます。サンプルのクエリを以下のように修正してみてください。
1
2
3
4
5
6
|
var result
= from row in human_table
where row.Sei == "male"
orderby row.Age
let fullname = row.SecondName + row.FirstName // 名字と下の名前を結合
select fullname; // resultにフルネームを入れる
|
結果は以下になります。
山田太郎
阿部伸介
佐藤一郎
クエリの中でも匿名クラスを生成できる
クエリの中でnewをして匿名クラスを生成することができます。サンプルのクエリ以降を以下のように修正してみてください。
1
2
3
4
5
6
7
8
9
10
|
var result
= from row in human_table
where row.Sei == "male"
orderby row.Age
select new { row.SecondName, row.FirstName }; // 名字と下の名前を返す
foreach (var name_set in result)
{
Console.WriteLine(name_set.SecondName+name_set.FirstName); // 結合して表示
}
|
これでletを使った時と同じ結果が表示されます。letを使うより、このようにクエリの外で計算をした方がやりやすい場合もあるでしょう。
Count、Max、Averageなどの使い方
C#のLINQのクエリは数値の項目に対して計算をすることもできます。以下はサンプルのhuman_tableの項目について様々な計算を行います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// データの項目の数
var cnt
= (from row in human_table
select row.SecondName).Count();
Console.WriteLine("人数は " + cnt + "人");
// 項目の最大値
var max
= (from row in human_table
select row.Age).Max();
Console.WriteLine("最高年齢は " + max + "才");
// 項目の平均値
var avg
= (from row in human_table
select row.Age).Average();
Console.WriteLine("平均年齢は " + avg + "才");
|
結果は以下になります。他にも最小値を出すMin()や合計値を出すSum()もあるので試してみてください。
人数は 4人
最高年齢は 41才
平均年齢は 28.5才
AnyとAllの使い方
取得したデータが条件を満たすかどうかチェックするにはAnyとAllを使います。以下はサンプルのhuman_tableの項目について判定を行います。判定文の=>はラムダ式ですね。
1
2
3
4
5
6
7
8
9
10
11
|
// Anyの条件を1つでも満たせばTrue
bool result1
= (from row in human_table
select row.Age).Any(age => age < 20);
Console.WriteLine("20歳未満がいるかどうか " + result1);
// Allの条件を全て満たせばTrue
bool result2
= (from row in human_table
select row.Age).All(age => age >= 20);
Console.WriteLine("全員が20歳以上かどうか " + result2);
|
結果は以下になります。human_tableの鈴木花子さんが18歳なのでAnyの条件はTrue、Allの条件はFalseになるということですね。
20歳未満がいるかどうか True
全員が20歳以上かどうか False
SelectManyで配列を取得できる
匿名型の配列にさらに配列が入っていた場合、それを取得するには以下のようにSelectManyを使います。なおLINQのこの機能はクエリ型でなくメソッド型で使用します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var syumi_table = new[]
{
new {SecondName = "山田", Syumi = new[]{ "サッカー”ゲーム" } },
new {SecondName = "鈴木", Syumi = new[]{ "ピアノ”読書" } },
new {SecondName = "佐藤", Syumi = new[]{ "ゴルフ”カラオケ" } },
new {SecondName = "阿部", Syumi = new[]{ "バンド”競馬" } },
};
var result = syumi_table
.Where(val=> val.SecondName != "鈴木")
.SelectMany(val=> val.Syumi); // Syumiを全て取得
foreach (var list in result)
{
Console.WriteLine(list);
}
|
このサンプルを実行すると以下のように表示されます。配列の中身がIEnumerableを実装しているコレクションとして取得されています。
サッカー
ゲーム
ゴルフ
カラオケ
バンド
競馬
joinで2つのデータを結合
joinを使うと2つのデータの共通点がある項目を結合することができます。ここまでのサンプルでhuman_tableとsyumi_tableという2つの匿名型の配列データが出てきましたが、これを結合してみましょう。join~in~on~equals~で可能です。以下がその例です。
1
2
3
4
5
6
7
8
9
|
var result
= from row in human_table
join row2 in syumi_table on row.SecondName equals row2.SecondName
select new[] { row.FirstName, row2.Syumi[0] };
foreach (var name_syumi in result)
{
Console.WriteLine(name_syumi[0]+”+name_syumi[1]);
}
|
human_tableとsyumi_tableのSecondNameは共通しているので、それが等しい箇所を結合します。実行すると以下のように表示されます。
太郎 サッカー
花子 ピアノ
一郎 ゴルフ
信介 バンド
group byで重複する箇所のあるデータをまとめる
例えばサンプルのsyumi_tableが以下のようになっていたら、SecondNameが同じ個所をまとめたいと思いますよね。
1
2
3
4
5
6
7
|
var syumi_table = new[]
{
new {SecondName = "山田", Syumi = "サッカー" },
new {SecondName = "山田", Syumi = "ゲーム" },
new {SecondName = "鈴木", Syumi = "ピアノ" },
new {SecondName = "鈴木", Syumi = "読書" },
};
|
group byを使えば同じ箇所があるデータをまとめることができます。以下が例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var result
= from row in syumi_table
group row.Syumi by row.SecondName; // SecondNameでSyumiをまとめる
foreach (var name_syumi in result)
{
Console.Write(name_syumi.Key+”);
foreach (var s in name_syumi)
{
Console.Write(s+”);
}
Console.WriteLine(“); // 改行
}
|
結果は以下になります。resultはIGroupingを実装したコレクションで、中身の要素のKeyにgroup byでまとめたSecondNameが入っています。
山田 サッカー ゲーム
鈴木 ピアノ 読書
さいごに
C#のLINQについて理解できましたでしょうか。今回のサンプルでは匿名クラスの配列データが対象でしたが、LINQは他にもXMLドキュメントやSQLデータベースを対象にすることもできます。C#でデータ検索のプロフェッショナルを目指すなら、是非LINQをマスターしましょう。
FEnetを運営しているネプラス株式会社はサービス開始から10年以上
『エンジニアの生涯価値の向上』をミッションに掲げ、
多くのインフラエンジニア・ネットワークエンジニアの就業を支援してきました。
ネプラス株式会社はこんな会社です
秋葉原オフィスにはネプラス株式会社をはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
インフラ業界に特化
ネットワーク・サーバー・データベース等、ITインフラ業界に特化。Cisco Systemsプレミアパートナーをはじめ各種ベンダーのパートナー企業です。
業界を知り尽くしているからこそ大手の取引先企業、経験豊富なエンジニアに選ばれています。
-
正社員なのにフリーランスのような働き方
正社員の方でも希望を聞いたうえでプロジェクトをアサインさせていただいており、フリーランスのような働き方が可能。帰社日もありません。
プロジェクト終了後もすぐに次の案件をご紹介させていただきますのでご安心ください。
-
大手直取引の高額案件
案件のほとんどが大手SIerやエンドユーザーからの直取引のためエンジニアの皆様へに高く還元できています。
Ciscoをはじめ、Juniper、Azure、Linux、AWS等インフラに特化した常時300件以上の案件があります。
-
スキルアップ支援
不要なコストを削減し、その分エンジニアの方へのスキルアップ支援(ネットワーク機器貸出、合格時の受験費用支給など)や給与で還元しています。
受験費用例)CCNP,CCIE:6-20万円、JNCIS:3-4万円、AWS:1-3万円など
※業務に関連する一定の資格のみ。各種条件がありますので詳しくは担当者へにお尋ねください。
-
現給与を保証します!※
前職の給与保証しており、昨年度は100%の方が給与アップを実現。収入面の不安がある方でも安心して入社していただけます。
※適用にはインフラエンジニアの業務経験1年以上、等一定の条件がございます。
-
インセンティブ制度
ネットワーク機器の販売・レンタル事業等、売上に貢献いただいた方にはインセンティブをお支払いしています。
取引先企業とエンジニア側、双方にメリットがあり大変好評をいただいています。
-
社会保険・福利厚生
社員の方は、社会保険を完備。健康保険は業界内で最も評価の高い「関東ITソフトウェア健康保険組合」です。
さらに様々なサービスをお得に利用できるベネフィットステーションにも加入いただきます。
-
東証プライム上場企業グループ
ネプラスは東証プライム上場「株式会社夢真ビーネックスグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
ネプラス株式会社に興味を持った方へ
ネプラス株式会社では、インフラエンジニアを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
オンライン面接も随時受付中。ぜひお気軽にご応募ください。


C#新着案件New Job
-
【高額年収】/競馬場向け音声案内ツール運用保守/神奈川県横浜市/【WEB面談可/インフラサーバ経験者/20~40代の方活躍中】/在宅勤務
年収600万~720万円神奈川県横浜市(桜木町駅) -
【高額年収】/ECサイト運用保守/Windows/東京都23区東部/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都23区東部(-駅) -
【高額年収】/共通基盤や製品に関わる運用保守/C#/東京都中野区/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都中野区(中野駅) -
ECサイト構築/Windows/東京都23区東部/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収540万~720万円東京都23区東部(-駅) -
VR・AIサービス運用保守/C#/東京都品川区/【WEB面談可】/在宅勤務/20代~40代の方活躍中
年収600万~720万円東京都品川区(五反田駅) -
Web受付ツール及びサーバ運用保守/東京都千代田区/【WEB面談可/インフラサーバ経験者/20~40代の方活躍中】/在宅勤務
年収480万~660万円東京都千代田区(飯田橋駅)