Assuming I have a left outer join as such:
from f in Foo
join b in Bar on f.Foo_Id equals b.Foo_Id into g
from result in g.DefaultIfEmpty()
select new { Foo
Turning Marc Gravell's answer into an extension method, I made the following.
internal static IEnumerable<Tuple<TLeft, TRight>> LeftJoin<TLeft, TRight, TKey>(
this IEnumerable<TLeft> left,
IEnumerable<TRight> right,
Func<TLeft, TKey> selectKeyLeft,
Func<TRight, TKey> selectKeyRight,
TRight defaultRight = default(TRight),
IEqualityComparer<TKey> cmp = null)
{
return left.GroupJoin(
right,
selectKeyLeft,
selectKeyRight,
(x, y) => new Tuple<TLeft, IEnumerable<TRight>>(x, y),
cmp ?? EqualityComparer<TKey>.Default)
.SelectMany(
x => x.Item2.DefaultIfEmpty(defaultRight),
(x, y) => new Tuple<TLeft, TRight>(x.Item1, y));
}