LINQとは?

LINQとは、Language Integrated Queryの略で「リンク」と読み見ます。

コレクションなどのデータの集まりに対して、SQLのようにデータを問い合わせる機能を

C#言語内で統一的に使用できるようにした物です。

LINQを使うと、コレクションから特定のデータを選択したり、抽出したり、並び替えたり、

などの操作を簡潔に記述できます。

参考データ

以下の様なデータ用クラスが合ったとします。

public class UserData
{
	public int Id;
	public string Name;
	public int Age;
}

適当なクラスの中で初期化したとしましょう。

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

public class UserDataTest : MonoBehaviour
{
	private List<UserData> _userDataList;
	
	private void Awake()
	{
        // 10人分のUserDataのリストを作成
        _userDataList = new List<UserData>
        {
            new UserData { Id = 1, Name = "John", Age = 25 },
            new UserData { Id = 2, Name = "Alice", Age = 30 },
            new UserData { Id = 3, Name = "Bob", Age = 22 },
            new UserData { Id = 4, Name = "Charlie", Age = 28 },
            new UserData { Id = 5, Name = "David", Age = 35 },
            new UserData { Id = 6, Name = "Eve", Age = 27 },
            new UserData { Id = 7, Name = "Frank", Age = 33 },
            new UserData { Id = 8, Name = "Grace", Age = 24 },
            new UserData { Id = 9, Name = "Hannah", Age = 29 },
            new UserData { Id = 10, Name = "Ivy", Age = 26 }
        };
	}
}

Awake()メソッドが呼ばれた後の、_userDataListは以下ような内容になっていることがイメージできるでしょうか?

検索する

GoogleSpreadSheet上だとフィルターを設定して条件にあうデータを絞り込むことが出来ます。

C#では、リストの中から条件にあう特定のデータを検索するには、通常forforeachで全データを調べることになります。

for(int i = 0; i < _userDataList.Count; i++)
{
	// Idが5のユーザーを探す
	if (_userDataList[i].Id == 5)
	{
		return _userDataList[i];
	}
}

LINQを使うことで簡潔に記述することが出来ます。

Whereで指定された条件に合う要素を絞り込む

Whereメソッドを使用すると条件にある要素を絞り込んで取り出すことが出来ます。

先ほどのfor文は以下の様に置き換えることが出来ます。

var users = _userDataList.Where(user => user.Id == 5);

Whereの引数には、_userDataList内のUserDataが順々に渡されてきます。

条件式がtrueになる場合は、最終的に戻り値に条件にある要素のコレクションが返ってきます。

Firstで最初に条件に合う要素を取得する

var user = _userDataList.First(user => user.Id == 5);

コレクションを先頭から調べて最初に条件にあう要素が見つかるとそれを返します。

Firstに引数を渡さなければコレクションの先頭を返します。

Lastで最後に条件に合う要素を取得する

var user = _userDataList.Last(user => user.Id == 5);

コレクションを最後から調べて最初に条件にあう要素が見つかるとそれを返します。

Lastに引数を渡さなければコレクションの最後を返します。

Singleで条件に合う要素を一つだけ取得する

var user = _userDataList.Single(user => user.Id == 5);

コレクションのうち、条件にある要素を一つだけ返します。

Firstと同じような挙動になるのであまり出番はないかもしれません。

Anyで条件にあう要素が1つでもあるか確認する

if (_userDataList.Any(user => user.Age <= 30))
{
	// 30歳以下のユーザーがいる
}

コレクションのうち、条件にあう要素が一つでもあるか確認します。

引数を省略すると、コレクションが空かどうかを判定することも出来ます。

Allで全ての要素が条件を満たしているか確認する

if (_userDataList.All(user => user.Age >= 20)
{
	 // 全員が20歳以上
}

コレクションの要素が、全て条件を満たしているか確認します。

Findで条件に合う要素を取得する

var user = _userDataList.Find(user => user.Id == 5);

List用のメソッドです。

条件にあう要素を1つだけ取得します。

First,Singleと同じ挙動になります。

FindAllで条件に合う要素を全て取得する

// 30歳以上のユーザーを全て取得
var users = _userDataList.FindAll(user => user.Age >= 30);

こちらもList用のメソッドです。

条件にある要素を全て取得します。

Whereと同じ挙動になります。

例外

First,Last,Singleメソッドは、該当するデータが見つからなかった場合例外を発生させます。

try
{
	var user = _users.First(user => user.Age <= 10);
}
catch(e)
{
	// 見つからなかった
}

例外を処理したくない場合のために、FirstOrDefault,LastOrDefault,SingleOrDefaultというメソッドがあります。

これらは、データが見つからなかった場合に例外を発生させず、

コレクションの型のdefault値を返します。

var user = _users.First(user => user.Age <= 10);
if (user == null)
{
		// 見つからなかった
}

classの場合はnullを返すので、結果がnullだった場合該当する要素が見つからなかったことになります。

まとめ

今回はLINQの検索編でした。

最初のfor文と比べるといずれも簡潔に記述できますで、ソースコード上の見通しも良くなります。

可読性やメンテナンス性が求められる現場では、コードの見通しが良くなるというメリットは大きいでしょう。

LINQを使うことで、複雑なデータ操作も直感的かつ簡潔に記述できるため、開発の効率が格段に上がります。

アプリケーション開発時に大量のデータから該当するものを検索するという場面はよくあると思いますので、

LINQを使える機会も多いと思いますので、是非活用してみてください。

🔗関連ページ