FirstOrDefaultやSingleOrDefaultでnull以外のデフォルト値を返したい場合の書き方


やりたいこと

FirstOrDefaultSingleOrDefaultを使用した時、条件に一致しない場合nullではなく任意のデフォルト値を返したい。

結論

DefaultIfEmpty を使う。
たぶん周知の事実なのだろうけど、調べた時にやりたい事どんぴしゃが無かったので忘備録として残します。

@Ryooooooga さんにコメントにて ??演算子を用いたもっと良い方法を教えて頂きました!ありがとうございます!

  • User.id をチェックし一致しない場合は id=-1 userName="NG" を返す。

サンプルに使用するクラス

public class User(){
    public int id {get;set;}
    public string userName {get; set;}
    public int age {get; set;}
    // ユーザーリストを返すメソッド
    public static List<User> GetUserList(){
        return new List<User> GetUserLists()
        {
            new User(){ id=1, userName="佐藤",age=20 },
            new User(){ id=2, userName="山田",age=30 },
            new User(){ id=3, userName="田中",age=28 },
    }
}

??演算子を使用する。

ID一致時は初期値インスタンスも生成されず、表記もスマートです。C#素晴らしい…

private User TestMethod2(int id){
    return User.GetUserList()
            .FirstOrDefault(x => x.ID == id)
            ?? new User { ID = -1, Name = "NG" };
}

DefaultIfEmptyを使用する場合

ラクチン!
IDが一致するデータが存在した場合も初期値のインスタンスが生成されてしまいます。

private User TestMethod2(int id){
    return User.GetUserList()
        .Where(x=>x.id == id)
        .DefaultIfEmpty(new User(){ id=-1, userName="NG" })
        .First();
}

if文を使用する場合

長い。

private User TestMethod(int id){
    var selectUser = User.GetUserList()
                    .FirstOrDefault(x=>x.id==id);
    if(selectUser != null){ 
        return selectUser;
    }else{
        return new User(){ id=-1, userName="NG" };
    }
}

参考URL

?? 演算子 (C# リファレンス)
Enumerable.FirstOrDefault(TSource) メソッド (IEnumerable(TSource)) (System.Linq)