MRが楽しい

MRやVRについて学習したことを書き残す

EnumerableのFirstで条件に合致する値が存在しなかった場合のデフォルト値を指定する

本日は C# の小ネタ枠です。
Enumerable の First で条件に合致する値が存在しなかった場合のデフォルト値を指定する方法について記事に残します。

Firstメソッド

First は指定した条件に合致する最初の要素を返します。
learn.microsoft.com

または合致する要素が見つからない場合は規定値(default)を返す FirstOrDefault が利用できます。
learn.microsoft.com

DefaultIfEmptyメソッド

シーケンスが空の場合は既定値を持つコレクションを返します。
返却する値は引数でも指定可能です。
learn.microsoft.com

サンプルコード

以下の3つの方法で検索を試すスクリプトを作成しました。

  • First メソッドで条件に合致する値を取得する
  • FirstOrDefault メソッドで条件に合致する値を取得する
  • DefaultIfEmpty メソッドでデフォルト値を指定して条件に合致する値を取得する

・FirstOrDefaultTest

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

public class FirstOrDefaultTest : MonoBehaviour
{
    [SerializeField] private List<MessageProfile> messageProfiles;
    [SerializeField] private string getType;
    
    /// <summary>
    /// First メソッドで条件に合致する値を取得する
    /// </summary>
    [ContextMenu("GetFirstMessage")]
    public void GetFirstMessage()
    {
        Debug.Log($"First : " +
                  $"{messageProfiles.First(profile => profile.Type == getType).Message}");
    }
    
    /// <summary>
    /// FirstOrDefault メソッドで条件に合致する値を取得する
    /// </summary>
    [ContextMenu("GetFirstOrDefaultMessage")]
    public void GetFirstOrDefaultMessage()
    {
        Debug.Log($"FirstOrDefault : " +
                  $"{messageProfiles.FirstOrDefault(profile => profile.Type == getType)?.Message}");
    }

    /// <summary>
    /// DefaultIfEmpty メソッドでデフォルト値を指定して条件に合致する値を取得する
    /// </summary>
    [ContextMenu("GetDefaultIfEmptyMessage")]
    public void GetDefaultIfEmptyMessage()
    {
        Debug.Log($"DefaultIfEmpty : " +
                  $"{messageProfiles.Where(profile => profile.Type == getType).DefaultIfEmpty(new MessageProfile()).First().Message}");
    }

    /// <summary>
    /// メッセージ定義
    /// </summary>
    [Serializable]
    private class MessageProfile
    {
        [SerializeField] private string type;
        [SerializeField] private string message;

        public string Type => type;
        public string Message => message;

        public MessageProfile()
        {
            this.type = "NONE";
            this.message = "None Message";
        }
    }
}

初めに条件に合致する値がある場合の動作を確認します。
結果は以下の通り、全ての方法で条件に合致する値が取得できます。

次に条件に合致する値が見つからなかった場合の動作です。
それぞれ以下のような動作になります。

First メソッドで条件に合致する値を取得する

InvalidOperationException が発生する。

FirstOrDefault メソッドで条件に合致する値を取得する

規定値(null)が返る。

DefaultIfEmpty メソッドでデフォルト値を指定して条件に合致する値を取得する

DefaultIfEmpty メソッドで指定したデフォルト値が返る。

このように DefaultIfEmpty メソッドを利用することで条件に合致する値が見つからなかった場合のデフォルト値を指定できます。