【C#】モダンな書き方に必要な最低限の知識まとめ

C#をメインの言語にして案件に参加しているのですが、そこで出会う人々のスキルは様々です。モダンな書き方を知っている人もいれば、そうでない人もいるわけで。ソースコードを書くにあたっての知識レベルも様々ですし、書き方についてもバラバラだったりします。

そんな中でも、少しでもモダンな書き方は押さえておきたいと思っています。そこでこの記事では、C#の案件で頑張っていくためにも知っておきたい「C#のモダンな書き方をするための最低限の知識」をまとめていきます。

C#のモダンな書き方とは

C#における「モダンな書き方」の中心となるのは明らかに「ラムダ式」の存在だと思っています。<そして、その恩恵を受けているのがLINQであり、このLINQという技術を中心にC#は進化してきたようにみえています。

それに伴ってデータの持ち方もデータテーブルといったものから、クラスを介したオブジェクト的なデータの持ち方をするようになりました。Generics、Collectionより使いやすくなっているように思います。

上記を踏まえて当記事で取り上げたいのが以下の3つの内容になります。決して最先端の技術とは言えないのですが、いま出回っている案件をきちっとこなすためにも知っておくべき内容だと思っています。

  • LINQ
  • Func / Action
  • Tuple(タプル)

と、その前にまずは「ラムダ式」について、簡単に概要を掴んでおきたいと思います。「C#」というプログラミング言語を語るうえでも重要な内容ですので概要はおさらいしておきましょう。

ラムダ式の基本概要

ラムダ式とは「関数を整数や変数と同様に扱うための手法」であり、「変数に関数を代入する際の関数の書き方の一つ」であります。推論で引数の型(intとかstring)を省略できます。また引数を囲む”()”も省略することができます。

private string testFunc = i => i.ToString();

例えば上記のような例では、iを文字列型(string型)に変換したものを戻り値として返却する関数になります。「=>」の部分はアロー関数と呼ばれ、別名「ラムダ演算子」とも呼ばれてます。

1.LINQ

C#といったらLINQといえるほど、重要な機能の一角となっている機能です。LINQを使いこなすことで、ソースコードの量を減らすことができるので、可読性の高いコードを書くことが可能となっています。もちろん、使い過ぎは逆効果となりますので注意が必要ですが。LINQの中で代表的な機能が以下の通り。

  1. 要素の取得と条件
  2. 集計
  3. 変換
  4. 判定
  5. 集合
  6. ソート

この中でも簡単に使えるものをいくつかピックアップして記載したいと思います。なお、下記の中で紹介しているAnyについては以下の記事でもまとめているので参考になると思います。

var list = new List { 1, 2, 3, 4, 5 }

// === 要素の取得 === //
//条件付取得
var selectedList = list.Where(x => x > 3);
//最初の要素
var firstList = list.First();
//最後の要素
var lastList = list.Last();

// === 集計 === //
//要素の平均
var averageList = list.Average();
//要素の合計
var sumList = list.Sum();
//要素の数
var count = list.Count();

// === 判定 === // 
//要素が存在するか
var isExist = list.Any();
//4より大きい要素が存在するか
var hasOverFour = list.Any(x => x > 4);

ざっくりとした形で提示してみました。LINQは「foreachがより便利になった機能」くらいにとらえておくと良いかもしれません。リストなどデータを保有しているオブジェクトに対して、強力な力を発揮してくれるC#の言語機能だということです。

そしてこの書き方は、現在のC#において推奨となっているので、様々な案件において、もはや「必須の知識」「最低限のスキル」といっても良いかもしれません。

2.Action / Func

ラムダ式を使った記述で、主に使われるのがActionとFuncです。LINQの知識があれば「なんとなく分かる」ものの、ちゃんと知っておかないと駄目な項目な気がしているので、ここで基本的なことを押さえておきたいと思っています。

Actionとは「戻り値のない処理(void)を記述するためのクラス」になり、Funcは「戻り値のある場合に処理を記述するためのクラス」ということになります。まずはActionのシンプルな使い方から。引数を持つ場合はAction<引数の型リスト>を使って記述します。

//引数のない場合
Action act = () => {
    Console.WriteLine("John Doe");
}

//引数のある場合
Action<int, string> act = (age, name) => {
    Console.WriteLine(string.Format("{0} is {1} years old.", name, age))
}

ラムダ式が戻り値を持つ場合はFuncを使って記述します。引数を持たない場合はFuncのみの定義、また引数を持つ場合はFunc<引数の型リスト>を使って記述すればOKです。

//引数なし、戻り値がbool
Func func = () => {
    return true;
}
//引数あり、戻り値がbool
Func<int, bool> func = (age) => {
    return age >= 20 ? true : false;
}

ActionやFuncを使って関数を記述しておくと、メソッド引数として引き渡すなどの使い方ができるようになります。JavaScriptで関数を渡せるようになるので、非常に便利な機能だと思います。関数を関数の引数にする方法は以下の記事に記載しています。

3.タプル

タプルはC#7.0から利用可能となった、複数のデータ要素をグループ化できる機能で便利です。各要素に明示的なフィールド名を持たせられるので、使い勝手が非常にいいなと感じています。ただし下記のサンプル2では型が推論となるので注意が必要かもしれません。

//サンプル1
(int Age, string Name) t = (12, "John");
Console.WriteLine($"{ t.Name }は{ t.Age }歳。");

//サンプル2
var t2 = (Age: 12, Name: "John");

また、タプルはメソッドの戻り値で複数の値を戻すときに有効ですし、Dictionaryとも相性が良く、キーとバリューをうまく使うことで、より効率的にデータを保管できる機能です。

//タプルで複合キー
var dic = new Dictionary<(int, int), string>();
dic.Add(Tuple.Create(1, 1), "元旦");

//値の取り出し
var nameOfHoliday = dic[Tuple.Create(1, 1)];

タプルを使うことでメソッドへのoutなどを使う必要がなくなります。まあ、私は必要なデータを複数持ちたい場合は、別でクラスを定義してデータを作成して戻すようにしちゃいますけどね。JavaScriptのオブジェクトのようなデータの定義方法があればいいのですが。

まとめ

C#でコーディングする際に、できる限りモダンな書き方をするために必要な最低限の知識について書いてみました。C#の開発はITの巨人であるMicrosoftが担っているため、今後も重要な役割を果たす言語だと思っています。

現在はLINQやラムダ式をあまり使いこなせていない世代と使いこなせる世代が入り混じって存在している「混沌」とした時代だと考えています。その中で重宝されるエンジニアになるためには、モダンな書き方について知っておくべきだと思います。