LoginSignup
26
33

More than 1 year has passed since last update.

よく作成するLinq拡張メソッドを紹介

Last updated at Posted at 2022-06-29

Linqにこんなメソッドあったら便利と、C#プロジェクトを作るたび、よく用意する拡張メソッドを紹介したいと思います。

Partition

条件に対してコレクションを絞りこむならWhereですが、trueだけではなくfalseも両方取りたい場合につかいます。

使用例

var (trueCollection, falseCollection) = _boolCollection.Partition(x => x == true);

実装

public static (List<T>, List<T>) Partition<T>(this IEnumerable<T> sequence, Func<T, bool> func)
{
    var incluedList = new List<T>();
    var excludeList = new List<T>();
    foreach (var x in sequence)
    {
        if (func(x))
            incluedList.Add(x);
        else
            excludeList.Add(x);
    };
    return (incluedList, excludeList);
}

NotNull

Linqでnullをはじく方法にWhere(x => x != null)ってやり方はあるんですが、これだと続けてSelect書こうとしてもWarningになってしまうため、非null型に変換も行ってくれるやつです。

作成する際の注意としては、クラスレベル or プロジェクトレベルでnullableをenableにしてください。

使用例

var_collection = new List<Test?>();
// 警告がでない
_collection.NotNull().Select(x => x.Property); 

後述の実装に関しては、versionごとの実装が記述してあります。

実装(version 1)

// クラス用
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> enumerable) where T : class
{
    return enumerable.Where(e => e != null).Select(e => e!);
}

// プリミティブ型用
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> enumerable) where T : struct
{
    return enumerable.Where(e => e.HasValue).Select(e => e!.Value);
}

コメントで.OfTypeで可能だと情報をいただきました。

このメソッドは 、型にキャストできる要素のみを返します。

こちらの実装であれば、クラス、プリミティブで分けて実装する必要はありません。

実装(version 2)

// クラス、プリミティブ型 兼用
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> enumerable)
{
    return enumerable.OfType<T>();
}

Diff

コレクションの片方にしかに要素を取得する
※注意としてはクラスなど参照型で使用する際は、参照比較になるため注意

使用例

var (onlyB, onlyA) = a.Diff(b);

実装

public static (IEnumerable<T>, IEnumerable<T>) Diff<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    var onlyB = b.Except(a);
    var onlyA = a.Except(b);
    return (onlyB, onlyA);
}

ForEach(index付き)

デフォルトのForEachのindexを第二引数に取れるバージョン

使用例

_collection.ForEach((x, index) => {});

実装

public static void ForEach<T>(this IEnumerable<T> sequence, Action<T, int> action)
{
    int i = 0;
    foreach (T item in sequence)
    {
        action(item, i);
        i++;
    }
}
26
33
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
33