---
title: IEnumerableExtensions
summary: API reference for IEnumerableExtensions.
status: draft
owner: saif-docgen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common
reference_type: package
---

# IEnumerableExtensions

General-purpose LINQ gap-fillers: eager iteration, string-joining, membership testing, trailing-item selection, keyed distinct, and full/left outer joins. ([BR-039](../../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-085](../../business-rules.md#br-085-joining-a-sequence-to-a-string-requires-a-non-null-separator)) through [BR-088](../../business-rules.md#br-088-outer-joins-compare-keys-with-the-caller's-iequalitycomparer%3Ctkey%3E-when-supplied%2C-otherwise-equalitycomparer%3Ctkey%3E.default%2C-and-substitute-caller-supplied-defaults-for-unmatched-sides)

## Purpose
- General-purpose LINQ gap-fillers: eager iteration, string-joining, membership testing, trailing-item selection, keyed distinct, and full/left outer joins. ([BR-039](../../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-085](../../business-rules.md#br-085-joining-a-sequence-to-a-string-requires-a-non-null-separator)) through [BR-088](../../business-rules.md#br-088-outer-joins-compare-keys-with-the-caller's-iequalitycomparer%3Ctkey%3E-when-supplied%2C-otherwise-equalitycomparer%3Ctkey%3E.default%2C-and-substitute-caller-supplied-defaults-for-unmatched-sides)

## Context
- Namespace: `SAIF.Common.Extensions`
- Assembly/package: `SAIF.Framework.Common`

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| ForEach<T>(this IEnumerable<T> source, Action<T> action) | `public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)` | Eagerly invokes `action` for every element of `source`. ([BR-039](../../business-rules.md#br-039-a-guarded-argument-must-not-be-null)) |
| ToStringAll<T>(this IEnumerable<T> source, string separator) | `public static string ToStringAll<T>(this IEnumerable<T> source, string separator)` | Joins each element's `ToString()` with `separator`. ([BR-039](../../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-085](../../business-rules.md#br-085-joining-a-sequence-to-a-string-requires-a-non-null-separator)) |
| ToStringAll<T>(this IEnumerable<T> source, string separator, Func<T,string> function) | `public static string ToStringAll<T>(this IEnumerable<T> source, string separator, Func<T,string> function)` | Joins each element's custom string projection with `separator`. ([BR-039](../../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-085](../../business-rules.md#br-085-joining-a-sequence-to-a-string-requires-a-non-null-separator)) |
| IsIn<T>(this T value, params T[] set) | `public static bool IsIn<T>(this T value, params T[] set)` | Tests whether `value` is a member of the supplied `set`. |
| TakeFromEnd<T>(this IEnumerable<T> source, int count) | `public static IEnumerable<T> TakeFromEnd<T>(this IEnumerable<T> source, int count)` | Returns the trailing `count` elements, preserving their original relative order. ([BR-086](../../business-rules.md#br-086-taking-n-items-from-the-end-of-a-sequence-preserves-their-original-relative-order)) |
| Distinct<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector) | `public static IEnumerable<TSource> Distinct<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)` | Returns the first element for each distinct key, a "distinct-by" LINQ does not provide natively. ([BR-087](../../business-rules.md#br-087-key-based-distinct-retains-the-first-occurrence-of-each-key)) |
| None<TSource>(this IEnumerable<TSource> source, Func<TSource,bool> predicate) | `public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource,bool> predicate)` | The negation of `Any(predicate)`. |
| ToLowerAll(this IEnumerable<string> source) | `public static IEnumerable<string> ToLowerAll(this IEnumerable<string> source)` | Lower-cases every string in the sequence. |
| FullOuterGroupJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,IEnumerable<TB>,TKey,TResult> projection, TA defaultA, TB defaultB, IEqualityComparer<TKey> comparer) | `public static IEnumerable<TResult> FullOuterGroupJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,IEnumerable<TB>,TKey,TResult> projection, TA defaultA = default(TA), TB defaultB = default(TB), IEqualityComparer<TKey> comparer = null)` | Full outer group-join over two sequences, substituting the supplied defaults where one side has no match. ([BR-088](../../business-rules.md#br-088-outer-joins-compare-keys-with-the-caller's-iequalitycomparer%3Ctkey%3E-when-supplied%2C-otherwise-equalitycomparer%3Ctkey%3E.default%2C-and-substitute-caller-supplied-defaults-for-unmatched-sides)) |
| FullOuterJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,TB,TKey,TResult> projection, TA defaultA, TB defaultB, IEqualityComparer<TKey> comparer) | `public static IEnumerable<TResult> FullOuterJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,TB,TKey,TResult> projection, TA defaultA = default(TA), TB defaultB = default(TB), IEqualityComparer<TKey> comparer = null)` | Full outer join over two sequences, substituting the supplied defaults where one side has no match. ([BR-088](../../business-rules.md#br-088-outer-joins-compare-keys-with-the-caller's-iequalitycomparer%3Ctkey%3E-when-supplied%2C-otherwise-equalitycomparer%3Ctkey%3E.default%2C-and-substitute-caller-supplied-defaults-for-unmatched-sides)) |
| LeftOuterJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,TB,TKey,TResult> projection, TB defaultB, IEqualityComparer<TKey> comparer) | `public static IEnumerable<TResult> LeftOuterJoin<TA,TB,TKey,TResult>(this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA,TKey> selectKeyA, Func<TB,TKey> selectKeyB, Func<TA,TB,TKey,TResult> projection, TB defaultB = default(TB), IEqualityComparer<TKey> comparer = null)` | Left outer join keyed only on the left sequence's keys, substituting `defaultB` where the right side has no match. ([BR-088](../../business-rules.md#br-088-outer-joins-compare-keys-with-the-caller's-iequalitycomparer%3Ctkey%3E-when-supplied%2C-otherwise-equalitycomparer%3Ctkey%3E.default%2C-and-substitute-caller-supplied-defaults-for-unmatched-sides)) |


## Sources
- `Common/SAIF.Common/Extensions/IEnumerableExtensions.cs`
