Click here to Skip to main content
15,892,674 members
Articles / Programming Languages / C#

Poor Man's LINQ in Visual Studio 2005

Rate me:
Please Sign up or sign in to vote.
4.53/5 (18 votes)
28 Oct 2010MIT3 min read 81.5K   619   34  
A way to use LINQ to Objects in C# 2.0 with .NET Framework 2.0
using System;
using System.Collections.Generic;
using System.Text;

namespace Compatibility.Linq
{
	/// <summary>A structure that provides Linq functionality in C# 2.0</summary>
	/// <typeparam name="T">Type of elements in the sequence to be processed</typeparam>
	/// <remarks>Please note that if you have access to C# 3.0, you do not need to
	/// use this class. Even if you are using .NET Framework 2.0, C# still allows
	/// you to use LINQ syntax; just add a reference to LinqBridge.dll in your
	/// project (LinqBridge provides an implementation of LINQ to Objects for the
	/// .NET framework 2.0. It is included in the Loyc distribution.
	/// 
	/// PoorMansLinq(of T) does not include all functionality of the static class
	/// Enumerable. It cannot not include specializations for specific kinds of T,
	/// such as Average&lt;double&gt;(). Nor does it include static methods such as
	/// Empty() and Range(first, last) that are not extension methods. And it
	/// doesn't include AsEnumerable(), which makes no sense without the extension
	/// methods feature.
	/// </remarks>
	public struct PoorMansLinq<T> : IEnumerable<T>
	{
		public IEnumerable<T> Collection;

		public PoorMansLinq(IEnumerable<T> collection) { Collection = collection; }

		#region Aggregate
		public T Aggregate(Func<T, T, T> func)
			{ return Enumerable.Aggregate(Collection, func); }
		public TAccumulate Aggregate<TAccumulate>(TAccumulate seed, Func<TAccumulate, T, TAccumulate> func)
			{ return Enumerable.Aggregate<T, TAccumulate>(Collection, seed, func); }
		public TResult Aggregate<TAccumulate, TResult>(TAccumulate seed, Func<TAccumulate, T, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
			{ return Enumerable.Aggregate<T, TAccumulate, TResult>(Collection, seed, func, resultSelector); }
		#endregion

		#region All
		public bool All(Func<T, bool> predicate)
			{ return Enumerable.All<T>(Collection, predicate); }
		#endregion

		#region Any
		public bool Any()
			{ return Enumerable.Any<T>(Collection); }
		public bool Any(Func<T, bool> predicate)
			{ return Enumerable.Any<T>(Collection); }
		#endregion

		#region Average
		/*
		// The following overloads cannot be supported here. Call Enumerable.Average() instead.
		public double Average(this IEnumerable<int> source)
		public double? Average(this IEnumerable<int?> source)
		public double Average(this IEnumerable<long> source)
		public double? Average(this IEnumerable<long?> source)
		public double Average(this IEnumerable<double> source)
		public double? Average(this IEnumerable<double?> source)
		public decimal Average(this IEnumerable<decimal> source)
		public decimal? Average(this IEnumerable<decimal?> source)
		*/
		public double Average(Func<T, int> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public double? Average(Func<T, int?> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public double Average(Func<T, long> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public double? Average(Func<T, long?> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public double Average(Func<T, double> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public double? Average(Func<T, double?> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public decimal Average(Func<T, decimal> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		public decimal? Average(Func<T, decimal?> selector)
			{ return Enumerable.Average<T>(Collection, selector); }
		#endregion

		#region Concat
		public PoorMansLinq<T> Concat(IEnumerable<T> second)
			{ return new PoorMansLinq<T>(Enumerable.Concat(Collection, second)); }
		#endregion

		#region Contains
		public bool Contains(T value)
			{ return Enumerable.Contains<T>(Collection, value); }
		public bool Contains(T value, IEqualityComparer<T> comparer)
			{ return Enumerable.Contains<T>(Collection, value, comparer); }
		#endregion

		#region Count
		public int Count()
			{ return Enumerable.Count<T>(Collection); }
		public int Count(Func<T, bool> selector)
			{ return Enumerable.Count<T>(Collection, selector); }
		#endregion

		#region DefaultIfEmpty
		public PoorMansLinq<T> DefaultIfEmpty()
			{ return new PoorMansLinq<T>(Enumerable.DefaultIfEmpty(Collection)); }
		public PoorMansLinq<T> DefaultIfEmpty(T defaultValue)
			{ return new PoorMansLinq<T>(Enumerable.DefaultIfEmpty(Collection, defaultValue)); }
		#endregion

		#region Distinct
		public PoorMansLinq<T> Distinct()
			{ return new PoorMansLinq<T>(Enumerable.Distinct<T>(Collection)); }
		public PoorMansLinq<T> Distinct(IEqualityComparer<T> comparer)
			{ return new PoorMansLinq<T>(Enumerable.Distinct<T>(Collection, comparer)); }
		#endregion

		#region ElementAt
		public T ElementAt(int index)
			{ return Enumerable.ElementAt<T>(Collection, index); }
		#endregion

		#region ElementAtOrDefault
		public T ElementAtOrDefault(int index)
			{ return Enumerable.ElementAtOrDefault<T>(Collection, index); }
		#endregion

		#region Except
		public PoorMansLinq<T> Except(IEnumerable<T> second)
			{ return new PoorMansLinq<T>(Enumerable.Except<T>(Collection, second)); }
		public PoorMansLinq<T> Except(IEnumerable<T> second, IEqualityComparer<T> comparer)
			{ return new PoorMansLinq<T>(Enumerable.Except<T>(Collection, second, comparer)); }
		#endregion

		#region First
		public T First()
			{ return Enumerable.First<T>(Collection); }
		public T First(Func<T, bool> predicate)
			{ return Enumerable.First<T>(Collection, predicate); }
		#endregion

		#region FirstOrDefault
		public T FirstOrDefault()
			{ return Enumerable.FirstOrDefault<T>(Collection); }
		public T FirstOrDefault(Func<T, bool> predicate)
			{ return Enumerable.FirstOrDefault<T>(Collection, predicate); }
		#endregion

		#region GroupBy
		public PoorMansLinq<IGrouping<TKey, T>> GroupBy<TKey>
			(Func<T, TKey> keySelector)
			{ return new PoorMansLinq<IGrouping<TKey, T>>(Enumerable.GroupBy<T, TKey>(Collection, keySelector)); }
		public PoorMansLinq<IGrouping<TKey, T>> GroupBy<TKey>
			(Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
			{ return new PoorMansLinq<IGrouping<TKey, T>>(Enumerable.GroupBy<T, TKey>(Collection, keySelector, comparer)); }
		public PoorMansLinq<IGrouping<TKey, TElement>> GroupBy<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector)
			{ return new PoorMansLinq<IGrouping<TKey, TElement>>(Enumerable.GroupBy<T, TKey, TElement>(Collection, keySelector, elementSelector)); }
		public PoorMansLinq<IGrouping<TKey, TElement>> GroupBy<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector, IEqualityComparer<TKey> comparer)
			{ return new PoorMansLinq<IGrouping<TKey, TElement>>(Enumerable.GroupBy<T, TKey, TElement>(Collection, keySelector, elementSelector, comparer)); }
		#endregion

		# region GroupJoin
		public PoorMansLinq<TResult> GroupJoin<TInner, TKey, TResult>
			(IEnumerable<TInner> inner, Func<T, TKey> outerKeySelector,
			Func<TInner, TKey> innerKeySelector, Func<T, IEnumerable<TInner>, TResult> resultSelector)
			{ return new PoorMansLinq<TResult>(Enumerable.GroupJoin<T, TInner, TKey, TResult>
				(Collection, inner, outerKeySelector, innerKeySelector, resultSelector)); }
		public PoorMansLinq<TResult> GroupJoin<TInner, TKey, TResult>
			(IEnumerable<TInner> inner, Func<T, TKey> outerKeySelector,
			Func<TInner, TKey> innerKeySelector, Func<T, IEnumerable<TInner>, TResult> resultSelector,
			IEqualityComparer<TKey> comparer)
			{ return new PoorMansLinq<TResult>(Enumerable.GroupJoin<T, TInner, TKey, TResult>
				(Collection, inner, outerKeySelector, innerKeySelector, resultSelector, comparer)); }
		#endregion

		#region Intersect
		public PoorMansLinq<T> Intersect(IEnumerable<T> second)
			{ return new PoorMansLinq<T>(Enumerable.Intersect<T>(Collection, second)); }
		#endregion

		#region Join
		public PoorMansLinq<TResult> Join<TInner, TKey, TResult>
			(IEnumerable<TInner> inner, Func<T, TKey> outerKeySelector,
			Func<TInner, TKey> innerKeySelector, Func<T, TInner, TResult> resultSelector)
			{ return new PoorMansLinq<TResult>(Enumerable.Join<T, TInner, TKey, TResult>
				(Collection, inner, outerKeySelector, innerKeySelector, resultSelector)); }
		public PoorMansLinq<TResult> Join<TInner, TKey, TResult>
			(IEnumerable<TInner> inner, Func<T, TKey> outerKeySelector,
			Func<TInner, TKey> innerKeySelector, Func<T, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
			{ return new PoorMansLinq<TResult>(Enumerable.Join<T, TInner, TKey, TResult>
				(Collection, inner, outerKeySelector, innerKeySelector, resultSelector, comparer)); }
		#endregion

		#region Last
		public T Last()
			{ return Enumerable.Last<T>(Collection); }
		public T Last(Func<T, bool> predicate)
			{ return Enumerable.Last<T>(Collection, predicate); }
		#endregion

		#region LastOrDefault
		public T LastOrDefault()
			{ return Enumerable.LastOrDefault<T>(Collection); }
		public T LastOrDefault(Func<T, bool> predicate)
			{ return Enumerable.LastOrDefault<T>(Collection, predicate); }
		#endregion

		#region LongCount
		public long LongCount()
			{ return Enumerable.LongCount<T>(Collection); }
		public long LongCount(Func<T, bool> selector)
			{ return Enumerable.LongCount<T>(Collection, selector); }
		#endregion

		#region Max
		/*
		// The following overloads cannot be supported here. Call Enumerable.Max() instead.
		public int Max(this IEnumerable<int> source)
		public int? Max(this IEnumerable<int?> source)
		public long Max(this IEnumerable<long> source)
		public long? Max(this IEnumerable<long?> source)
		public double Max(this IEnumerable<double> source)
		public double? Max(this IEnumerable<double?> source)
		public decimal Max(this IEnumerable<decimal> source)
		public decimal? Max(this IEnumerable<decimal?> source)
		*/
		public T Max()
			{ return Enumerable.Max<T>(Collection); }
		public int Max(Func<T, int> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public int? Max(Func<T, int?> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public long Max(Func<T, long> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public long? Max(Func<T, long?> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public double Max(Func<T, double> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public double? Max(Func<T, double?> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public decimal Max(Func<T, decimal> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public decimal? Max(Func<T, decimal?> selector)
			{ return Enumerable.Max<T>(Collection, selector); }
		public TResult Max<TResult>(Func<T, TResult> selector)
			{ return Enumerable.Max<T, TResult>(Collection, selector); }
		#endregion

		#region Min
		/*
		// The following overloads cannot be supported here. Call Enumerable.Min() instead.
		public int Min(this IEnumerable<int> source)
		public int? Min(this IEnumerable<int?> source)
		public long Min(this IEnumerable<long> source)
		public long? Min(this IEnumerable<long?> source)
		public double Min(this IEnumerable<double> source)
		public double? Min(this IEnumerable<double?> source)
		public decimal Min(this IEnumerable<decimal> source)
		public decimal? Min(this IEnumerable<decimal?> source)
		*/
		public T Min()
			{ return Enumerable.Min<T>(Collection); }
		public int Min(Func<T, int> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public int? Min(Func<T, int?> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public long Min(Func<T, long> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public long? Min(Func<T, long?> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public double Min(Func<T, double> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public double? Min(Func<T, double?> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public decimal Min(Func<T, decimal> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public decimal? Min(Func<T, decimal?> selector)
			{ return Enumerable.Min<T>(Collection, selector); }
		public TResult Min<TResult>(Func<T, TResult> selector)
			{ return Enumerable.Min<T, TResult>(Collection, selector); }
		#endregion

		#region OrderBy
		public PoorMansLinq<T> OrderBy<TKey>(Func<T, TKey> keySelector)
			{ return new PoorMansLinq<T>(Enumerable.OrderBy(Collection, keySelector)); }
		public PoorMansLinq<T> OrderBy<TKey>
			(Func<T, TKey> keySelector, IComparer<TKey> comparer)
			{ return new PoorMansLinq<T>(Enumerable.OrderBy(Collection, keySelector, comparer)); }
		#endregion

		#region OrderByDescending
		public PoorMansLinq<T> OrderByDescending<TKey>
			(Func<T, TKey> keySelector)
			{ return new PoorMansLinq<T>(Enumerable.OrderByDescending<T, TKey>(Collection, keySelector)); }
		public PoorMansLinq<T> OrderByDescending<TKey>
			(Func<T, TKey> keySelector, IComparer<TKey> comparer)
			{ return new PoorMansLinq<T>(Enumerable.OrderByDescending<T, TKey>(Collection, keySelector, comparer)); }
		#endregion

		#region Reverse
		public PoorMansLinq<T> Reverse()
			{ return new PoorMansLinq<T>(Enumerable.Reverse(Collection)); }
		#endregion

		#region Select
		public PoorMansLinq<TResult> Select<TResult>(Func<T, TResult> selector)
			{ return new PoorMansLinq<TResult>(Enumerable.Select<T, TResult> (Collection, selector)); }
		public PoorMansLinq<TResult> Select<TResult>(Func<T, int, TResult> selector)
			{ return new PoorMansLinq<TResult>(Enumerable.Select<T, TResult> (Collection, selector)); }
		#endregion

		#region SelectMany
		public PoorMansLinq<TResult> SelectMany<TResult>(Func<T, IEnumerable<TResult>> selector)
			{ return new PoorMansLinq<TResult>(Enumerable.SelectMany<T, TResult>(Collection, selector)); }
		public PoorMansLinq<TResult> SelectMany<TResult>(Func<T, int, IEnumerable<TResult>> selector)
			{ return new PoorMansLinq<TResult>(Enumerable.SelectMany<T, TResult>(Collection, selector)); }
		#endregion

		#region Single

		public T Single()
			{ return Enumerable.Single<T>(Collection); }
		public T Single(Func<T, bool> predicate)
			{ return Enumerable.Single<T>(Collection, predicate); }
		#endregion

		#region SingleOrDefault
		public T SingleOrDefault()
			{ return Enumerable.SingleOrDefault<T>(Collection); }
		public T SingleOrDefault(Func<T, bool> predicate)
			{ return Enumerable.SingleOrDefault<T>(Collection, predicate); }
		#endregion

		#region Skip
		public PoorMansLinq<T> Skip(int count)
			{ return new PoorMansLinq<T>(Enumerable.Skip<T>(Collection, count)); }
		#endregion

		#region SkipWhile
		public PoorMansLinq<T> SkipWhile(Func<T, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.SkipWhile<T>(Collection, predicate)); }
		public PoorMansLinq<T> SkipWhile(Func<T, int, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.SkipWhile(Collection, predicate)); }
		#endregion

		#region Sum
		/*
		// The following overloads cannot be supported here. Call Enumerable.Sum() instead.
		public int Sum(this IEnumerable<int> source)
		public int? Sum(this IEnumerable<int?> source)
		public long Sum(this IEnumerable<long> source)
		public long? Sum(this IEnumerable<long?> source)
		public double Sum(this IEnumerable<double> source)
		public double? Sum(this IEnumerable<double?> source)
		public decimal Sum(this IEnumerable<decimal> source)
		public decimal? Sum(this IEnumerable<decimal?> source)
		*/
		public int Sum(Func<T, int> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public int? Sum(Func<T, int?> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public long Sum(Func<T, long> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public long? Sum(Func<T, long?> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public double Sum(Func<T, double> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public double? Sum(Func<T, double?> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public decimal Sum(Func<T, decimal> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		public decimal? Sum(Func<T, decimal?> selector)
			{ return Enumerable.Sum<T>(Collection, selector); }
		#endregion
		
		#region Take
		public PoorMansLinq<T> Take(int count)
			{ return new PoorMansLinq<T>(Enumerable.Take<T>(Collection, count)); }
		#endregion

		#region TakeWhile
		public PoorMansLinq<T> TakeWhile(Func<T, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.TakeWhile<T>(Collection, predicate)); }
		public PoorMansLinq<T> TakeWhile(Func<T, int, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.TakeWhile<T>(Collection, predicate)); }
		#endregion

		#region ThenBy
		public PoorMansLinq<T> ThenBy<TKey>(Func<T, TKey> keySelector)
			{ return new PoorMansLinq<T>(Enumerable.ThenBy<T, TKey>((OrderedSequence<T>)Collection, keySelector)); }
		public PoorMansLinq<T> ThenBy<TKey>
			(Func<T, TKey> keySelector, IComparer<TKey> comparer)
			{ return new PoorMansLinq<T>(Enumerable.ThenBy<T, TKey>((OrderedSequence<T>)Collection, keySelector, comparer)); }
		#endregion

		#region ThenByDescending
		public PoorMansLinq<T> ThenByDescending<TKey>(Func<T, TKey> keySelector)
			{ return new PoorMansLinq<T>(Enumerable.ThenBy<T, TKey>((OrderedSequence<T>)Collection, keySelector)); }
		public PoorMansLinq<T> ThenByDescending<TKey>
			(Func<T, TKey> keySelector, IComparer<TKey> comparer)
			{ return new PoorMansLinq<T>(Enumerable.ThenBy<T, TKey>((OrderedSequence<T>)Collection, keySelector, comparer)); }
		#endregion

		#region ToArray
		public T[] ToArray()
			{ return Enumerable.ToArray<T>(Collection); }
		#endregion

		#region ToDictionary
		public Dictionary<TKey, TElement> ToDictionary<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector)
			{ return Enumerable.ToDictionary<T, TKey, TElement>(Collection, keySelector, elementSelector); }
		public Dictionary<TKey, TElement> ToDictionary<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector, IEqualityComparer<TKey> comparer)
			{ return Enumerable.ToDictionary<T, TKey, TElement>(Collection, keySelector, elementSelector, comparer); }
		#endregion

		#region ToList
		public List<T> ToList()
			{ return Enumerable.ToList<T>(Collection); }
		#endregion

		#region ToLookup
		public Lookup<TKey, T> ToLookup<TKey>(Func<T, TKey> keySelector)
			{ return Enumerable.ToLookup<T, TKey>(Collection, keySelector); }
		public Lookup<TKey, T> ToLookup<TKey>
			(Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
			{ return Enumerable.ToLookup<T, TKey>(Collection, keySelector, comparer); }
		public Lookup<TKey, TElement> ToLookup<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector)
			{ return Enumerable.ToLookup<T, TKey, TElement>(Collection, keySelector, elementSelector); }
		public Lookup<TKey, TElement> ToLookup<TKey, TElement>
			(Func<T, TKey> keySelector, Func<T, TElement> elementSelector, IEqualityComparer<TKey> comparer)
			{ return Enumerable.ToLookup<T, TKey, TElement>(Collection, keySelector, elementSelector, comparer); }
		#endregion

		#region Union
		public PoorMansLinq<T> Union(IEnumerable<T> second)
			{ return new PoorMansLinq<T>(Enumerable.Union<T>(Collection, second)); }
		#endregion

		#region Where
		public PoorMansLinq<T> Where(Func<T, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.Where<T>(Collection, predicate)); }
		public PoorMansLinq<T> Where(Func<T, int, bool> predicate)
			{ return new PoorMansLinq<T>(Enumerable.Where<T>(Collection, predicate)); }
		#endregion

		#region Cast, OfType
		public PoorMansLinq<TResult> Cast<TResult>()
		{
			return new PoorMansLinq<TResult>(Enumerable.Cast<TResult>(Collection));
		}
		public PoorMansLinq<TResult> OfType<TResult>()
		{
			return new PoorMansLinq<TResult>(Enumerable.OfType<TResult>(Collection));
		}
		#endregion

		// These methods are not included in the
		// .NET Standard Query Operators Specification,
		// but they provide additional useful commands

		public int IndexOf(T item, IEqualityComparer<T> comparer)
			{ return Enumerable.IndexOf<T>(Collection, item, comparer); }
		public int IndexOf(T item)
			{ return Enumerable.IndexOf<T>(Collection, item); }
		public PoorMansLinq<T> Sorted()
			{ return new PoorMansLinq<T>(Enumerable.OrderBy<T, T>(Collection, delegate(T t) { return t; })); }

		#region IEnumerable<T> Members

		public IEnumerator<T> GetEnumerator()
		{
			return Collection.GetEnumerator();
		}
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return Collection.GetEnumerator();
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer None
Canada Canada
Since I started programming when I was 11, I wrote the SNES emulator "SNEqr", the FastNav mapping component, the Enhanced C# programming language (in progress), the parser generator LLLPG, and LES, a syntax to help you start building programming languages, DSLs or build systems.

My overall focus is on the Language of your choice (Loyc) initiative, which is about investigating ways to improve interoperability between programming languages and putting more power in the hands of developers. I'm also seeking employment.

Comments and Discussions