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++;
}
}