LINQ
Introduction#
LINQ (Language Integrated Query) is an expression that retrieves data from a data source. LINQ simplifies this situation by offering a consistent model for working with data across various kinds of data sources and formats. In a LINQ query, you are always working with objects. You use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET Datasets, .NET collections, and any other format for which a provider is available. LINQ can be used in C# and VB.
Syntax#
- public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
- public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
- public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
- public static Boolean All<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static Boolean Any<TSource>(this IEnumerable<TSource> source)
- public static Boolean Any<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
- public static Decimal Average(this IEnumerable<Decimal> source)
- public static Double Average(this IEnumerable<Double> source)
- public static Double Average(this IEnumerable<Int32> source)
- public static Double Average(this IEnumerable<Int64> source)
- public static Nullable<Decimal> Average(this IEnumerable<Nullable<Decimal>> source)
- public static Nullable<Double> Average(this IEnumerable<Nullable<Double>> source)
- public static Nullable<Double> Average(this IEnumerable<Nullable<Int32>> source)
- public static Nullable<Double> Average(this IEnumerable<Nullable<Int64>> source)
- public static Nullable<Single> Average(this IEnumerable<Nullable<Single>> source)
- public static Single Average(this IEnumerable<Single> source)
- public static Decimal Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Decimal> selector)
- public static Double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selector)
- public static Double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32> selector)
- public static Double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Int64> selector)
- public static Nullable<Decimal> Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Decimal>> selector)
- public static Nullable<Double> Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Double>> selector)
- public static Nullable<Double> Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int32>> selector)
- public static Nullable<Double> Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int64>> selector)
- public static Nullable<Single> Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Single>> selector)
- public static Single Average<TSource>(this IEnumerable<TSource> source, Func<TSource, Single> selector)
- public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
- public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
- public static Boolean Contains<TSource>(this IEnumerable<TSource> source, TSource value)
- public static Boolean Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
- public static Int32 Count<TSource>(this IEnumerable<TSource> source)
- public static Int32 Count<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source)
- public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
- public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source)
- public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
- public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, Int32 index)
- public static TSource ElementAtOrDefault<TSource>(this IEnumerable<TSource> source, Int32 index)
- public static IEnumerable<TResult> Empty<TResult>()
- public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
- public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
- public static TSource First<TSource>(this IEnumerable<TSource> source)
- public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
- public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
- public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer,IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
- public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
- public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
- public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
- public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
- public static TSource Last<TSource>(this IEnumerable<TSource> source)
- public static TSource Last<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source)
- public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static Int64 LongCount<TSource>(this IEnumerable<TSource> source)
- public static Int64 LongCount<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static Decimal Max(this IEnumerable<Decimal> source)
- public static Double Max(this IEnumerable<Double> source)
- public static Int32 Max(this IEnumerable<Int32> source)
- public static Int64 Max(this IEnumerable<Int64> source)
- public static Nullable<Decimal> Max(this IEnumerable<Nullable<Decimal>> source)
- public static Nullable<Double> Max(this IEnumerable<Nullable<Double>> source)
- public static Nullable<Int32> Max(this IEnumerable<Nullable<Int32>> source)
- public static Nullable<Int64> Max(this IEnumerable<Nullable<Int64>> source)
- public static Nullable<Single> Max(this IEnumerable<Nullable<Single>> source)
- public static Single Max(this IEnumerable<Single> source)
- public static TSource Max<TSource>(this IEnumerable<TSource> source)
- public static Decimal Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Decimal> selector)
- public static Double Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selector)
- public static Int32 Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32> selector)
- public static Int64 Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Int64> selector)
- public static Nullable<Decimal> Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Decimal>> selector)
- public static Nullable<Double> Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Double>> selector)
- public static Nullable<Int32> Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int32>> selector)
- public static Nullable<Int64> Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int64>> selector)
- public static Nullable<Single> Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Single>> selector)
- public static Single Max<TSource>(this IEnumerable<TSource> source, Func<TSource, Single> selector)
- public static TResult Max<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
- public static Decimal Min(this IEnumerable<Decimal> source)
- public static Double Min(this IEnumerable<Double> source)
- public static Int32 Min(this IEnumerable<Int32> source)
- public static Int64 Min(this IEnumerable<Int64> source)
- public static Nullable<Decimal> Min(this IEnumerable<Nullable<Decimal>> source)
- public static Nullable<Double> Min(this IEnumerable<Nullable<Double>> source)
- public static Nullable<Int32> Min(this IEnumerable<Nullable<Int32>> source)
- public static Nullable<Int64> Min(this IEnumerable<Nullable<Int64>> source)
- public static Nullable<Single> Min(this IEnumerable<Nullable<Single>> source)
- public static Single Min(this IEnumerable<Single> source)
- public static TSource Min<TSource>(this IEnumerable<TSource> source)
- public static Decimal Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Decimal> selector)
- public static Double Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selector)
- public static Int32 Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32> selector)
- public static Int64 Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Int64> selector)
- public static Nullable<Decimal> Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Decimal>> selector)
- public static Nullable<Double> Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Double>> selector)
- public static Nullable<Int32> Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int32>> selector)
- public static Nullable<Int64> Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int64>> selector)
- public static Nullable<Single> Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Single>> selector)
- public static Single Min<TSource>(this IEnumerable<TSource> source, Func<TSource, Single> selector)
- public static TResult Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
- public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
- public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
- public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
- public static IEnumerable<Int32> Range(Int32 start, Int32 count)
- public static IEnumerable<TResult> Repeat<TResult>(TResult element, Int32 count)
- public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source)
- public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
- public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, Int32, TResult> selector)
- public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
- public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, Int32, IEnumerable<TResult>> selector)
- public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
- public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, Int32, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
- public static Boolean SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
- public static Boolean SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
- public static TSource Single<TSource>(this IEnumerable<TSource> source)
- public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source)
- public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, Int32 count)
- public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
- public static Decimal Sum(this IEnumerable<Decimal> source)
- public static Double Sum(this IEnumerable<Double> source)
- public static Int32 Sum(this IEnumerable<Int32> source)
- public static Int64 Sum(this IEnumerable<Int64> source)
- public static Nullable<Decimal> Sum(this IEnumerable<Nullable<Decimal>> source)
- public static Nullable<Double> Sum(this IEnumerable<Nullable<Double>> source)
- public static Nullable<Int32> Sum(this IEnumerable<Nullable<Int32>> source)
- public static Nullable<Int64> Sum(this IEnumerable<Nullable<Int64>> source)
- public static Nullable<Single> Sum(this IEnumerable<Nullable<Single>> source)
- public static Single Sum(this IEnumerable<Single> source)
- public static Decimal Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Decimal> selector)
- public static Double Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selector)
- public static Int32 Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32> selector)
- public static Int64 Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Int64> selector)
- public static Nullable<Decimal> Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Decimal>> selector)
- public static Nullable<Double> Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Double>> selector)
- public static Nullable<Int32> Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int32>> selector)
- public static Nullable<Int64> Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Int64>> selector)
- public static Nullable<Single> Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Nullable<Single>> selector)
- public static Single Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, Single> selector)
- public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, Int32 count)
- public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
- public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
- public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
- public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
- public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
- public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
- public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
- public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
- public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
- public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
- public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
- public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
- public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
- public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
- public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
- public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
Remarks#
- See also LINQ.
The LINQ built-in methods are extension methods for the IEnumerable<T>
interface that live in the System.Linq.Enumerable
class in the System.Core
assembly. They are available in .NET Framework 3.5 and later.
LINQ allows for simple modification, transformation, and combination of various IEnumerable
s using a query-like or functional syntax.
While the standard LINQ methods can work on any IEnumerable<T>
, including the simple arrays and List<T>
s, they can also be used on database objects, where the set of LINQ expressions can be transformed in many cases to SQL if the data object supports it. See LINQ to SQL.
For the methods that compare objects (such as Contains
and Except
), IEquatable<T>.Equals
is used if the type T of the collection implements that interface. Otherwise, the standard Equals
and GetHashCode
of the type (possibly overriden from the default Object
implementations) are used. There are also overloads for these methods that allow to specify a custom IEqualityComparer<T>
.
For the ...OrDefault
methods, default(T)
is used to generate default values.
Official reference: Enumerable class
Lazy Evaluation
Virtually every query that returns an IEnumerable<T>
is not evaluated immediately; instead, the logic is delayed until the query is iterated over. One implication is that each time someone iterates over an IEnumerable<T>
created from one of these queries, e.g., .Where()
, the full query logic is repeated. If the predicate is long-running, this can be a cause for performance issues.
One simple solution (when you know or can control the approximate size of the resulting sequence) is to fully buffer the results using .ToArray()
or .ToList()
. .ToDictionary()
or .ToLookup()
can fulfill the same role. One can also, of course, iterate over the entire sequence and buffer the elements according to other custom logic.
ToArray()
or ToList()
?
Both .ToArray()
and .ToList()
loop through all elements of an IEnumerable<T>
sequence and save the results in a collection stored in-memory. Use the following guidelines to determine which to choose:
-
Some APIs may require a
T[]
or aList<T>
. -
.ToList()
typically runs faster and generates less garbage than.ToArray()
, because the latter must copy all the elements into a new fixed-size collection one more time than the former, in almost every case. -
Elements can be added to or removed from the
List<T>
returned by.ToList()
, whereas theT[]
returned from.ToArray()
remains a fixed size throughout its lifetime. In other words,List<T>
is mutable, andT[]
is immutable. -
The
T[]
returned from.ToArray()
uses less memory than theList<T>
returned from.ToList()
, so if the result is going to be stored for a long time, prefer.ToArray()
. CallingList<T>.TrimExcess()
would make the memory difference strictly academic, at the cost of eliminating the relative speed advantage of.ToList()
.
Select (map)
var persons = new[]
{
new {Id = 1, Name = "Foo"},
new {Id = 2, Name = "Bar"},
new {Id = 3, Name = "Fizz"},
new {Id = 4, Name = "Buzz"}
};
var names = persons.Select(p => p.Name);
Console.WriteLine(string.Join(",", names.ToArray()));
//Foo,Bar,Fizz,Buzz
This type of function is usually called map
in functional programming languages.
Where (filter)
This method returns an IEnumerable with all the elements that meets the lambda expression
Example
var personNames = new[]
{
"Foo", "Bar", "Fizz", "Buzz"
};
var namesStartingWithF = personNames.Where(p => p.StartsWith("F"));
Console.WriteLine(string.Join(",", namesStartingWithF));
Output:
Foo,Fizz
OrderBy
var persons = new[]
{
new {Id = 1, Name = "Foo"},
new {Id = 2, Name = "Bar"},
new {Id = 3, Name = "Fizz"},
new {Id = 4, Name = "Buzz"}
};
var personsSortedByName = persons.OrderBy(p => p.Name);
Console.WriteLine(string.Join(",", personsSortedByName.Select(p => p.Id).ToArray()));
//2,4,3,1
OrderByDescending
var persons = new[]
{
new {Id = 1, Name = "Foo"},
new {Id = 2, Name = "Bar"},
new {Id = 3, Name = "Fizz"},
new {Id = 4, Name = "Buzz"}
};
var personsSortedByNameDescending = persons.OrderByDescending(p => p.Name);
Console.WriteLine(string.Join(",", personsSortedByNameDescending.Select(p => p.Id).ToArray()));
//1,3,4,2
Contains
var numbers = new[] {1,2,3,4,5};
Console.WriteLine(numbers.Contains(3)); //True
Console.WriteLine(numbers.Contains(34)); //False
Except
var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbersBetweenSixAndFourteen = new[] { 6, 8, 10, 12 };
var result = numbers.Except(evenNumbersBetweenSixAndFourteen);
Console.WriteLine(string.Join(",", result));
//1, 2, 3, 4, 5, 7, 9
Intersect
var numbers1to10 = new[] {1,2,3,4,5,6,7,8,9,10};
var numbers5to15 = new[] {5,6,7,8,9,10,11,12,13,14,15};
var numbers5to10 = numbers1to10.Intersect(numbers5to15);
Console.WriteLine(string.Join(",", numbers5to10));
//5,6,7,8,9,10
Concat
var numbers1to5 = new[] {1, 2, 3, 4, 5};
var numbers4to8 = new[] {4, 5, 6, 7, 8};
var numbers1to8 = numbers1to5.Concat(numbers4to8);
Console.WriteLine(string.Join(",", numbers1to8));
//1,2,3,4,5,4,5,6,7,8
Note that duplicates are kept in the result. If this is undesirable, use Union
instead.
First (find)
var numbers = new[] {1,2,3,4,5};
var firstNumber = numbers.First();
Console.WriteLine(firstNumber); //1
var firstEvenNumber = numbers.First(n => (n & 1) == 0);
Console.WriteLine(firstEvenNumber); //2
The following throws InvalidOperationException
with message “Sequence contains no matching element”:
var firstNegativeNumber = numbers.First(n => n < 0);
Single
var oneNumber = new[] {5};
var theOnlyNumber = oneNumber.Single();
Console.WriteLine(theOnlyNumber); //5
var numbers = new[] {1,2,3,4,5};
var theOnlyNumberSmallerThanTwo = numbers.Single(n => n < 2);
Console.WriteLine(theOnlyNumberSmallerThanTwo); //1
The following throws InvalidOperationException
since there is more than one element in the sequence:
var theOnlyNumberInNumbers = numbers.Single();
var theOnlyNegativeNumber = numbers.Single(n => n < 0);
Last
var numbers = new[] {1,2,3,4,5};
var lastNumber = numbers.Last();
Console.WriteLine(lastNumber); //5
var lastEvenNumber = numbers.Last(n => (n & 1) == 0);
Console.WriteLine(lastEvenNumber); //4
The following throws InvalidOperationException
:
var lastNegativeNumber = numbers.Last(n => n < 0);
LastOrDefault
var numbers = new[] {1,2,3,4,5};
var lastNumber = numbers.LastOrDefault();
Console.WriteLine(lastNumber); //5
var lastEvenNumber = numbers.LastOrDefault(n => (n & 1) == 0);
Console.WriteLine(lastEvenNumber); //4
var lastNegativeNumber = numbers.LastOrDefault(n => n < 0);
Console.WriteLine(lastNegativeNumber); //0
var words = new[] { "one", "two", "three", "four", "five" };
var lastWord = words.LastOrDefault();
Console.WriteLine(lastWord); // five
var lastLongWord = words.LastOrDefault(w => w.Length > 4);
Console.WriteLine(lastLongWord); // three
var lastMissingWord = words.LastOrDefault(w => w.Length > 5);
Console.WriteLine(lastMissingWord); // null
SingleOrDefault
var oneNumber = new[] {5};
var theOnlyNumber = oneNumber.SingleOrDefault();
Console.WriteLine(theOnlyNumber); //5
var numbers = new[] {1,2,3,4,5};
var theOnlyNumberSmallerThanTwo = numbers.SingleOrDefault(n => n < 2);
Console.WriteLine(theOnlyNumberSmallerThanTwo); //1
var theOnlyNegativeNumber = numbers.SingleOrDefault(n => n < 0);
Console.WriteLine(theOnlyNegativeNumber); //0
The following throws InvalidOperationException
:
var theOnlyNumberInNumbers = numbers.SingleOrDefault();
FirstOrDefault
var numbers = new[] {1,2,3,4,5};
var firstNumber = numbers.FirstOrDefault();
Console.WriteLine(firstNumber); //1
var firstEvenNumber = numbers.FirstOrDefault(n => (n & 1) == 0);
Console.WriteLine(firstEvenNumber); //2
var firstNegativeNumber = numbers.FirstOrDefault(n => n < 0);
Console.WriteLine(firstNegativeNumber); //0
var words = new[] { "one", "two", "three", "four", "five" };
var firstWord = words.FirstOrDefault();
Console.WriteLine(firstWord); // one
var firstLongWord = words.FirstOrDefault(w => w.Length > 3);
Console.WriteLine(firstLongWord); // three
var firstMissingWord = words.FirstOrDefault(w => w.Length > 5);
Console.WriteLine(firstMissingWord); // null
Any
Returns true
if the collection has any elements that meets the condition in the lambda expression:
var numbers = new[] {1,2,3,4,5};
var isNotEmpty = numbers.Any();
Console.WriteLine(isNotEmpty); //True
var anyNumberIsOne = numbers.Any(n => n == 1);
Console.WriteLine(anyNumberIsOne); //True
var anyNumberIsSix = numbers.Any(n => n == 6);
Console.WriteLine(anyNumberIsSix); //False
var anyNumberIsOdd = numbers.Any(n => (n & 1) == 1);
Console.WriteLine(anyNumberIsOdd); //True
var anyNumberIsNegative = numbers.Any(n => n < 0);
Console.WriteLine(anyNumberIsNegative); //False
All
var numbers = new[] {1,2,3,4,5};
var allNumbersAreOdd = numbers.All(n => (n & 1) == 1);
Console.WriteLine(allNumbersAreOdd); //False
var allNumbersArePositive = numbers.All(n => n > 0);
Console.WriteLine(allNumbersArePositive); //True
Note that the All
method functions by checking for the first element to evaluate as false
according to the predicate. Therefore, the method will return true
for any predicate in the case that the set is empty:
var numbers = new int[0];
var allNumbersArePositive = numbers.All(n => n > 0);
Console.WriteLine(allNumbersArePositive); //True
SelectMany (flat map)
Enumerable.Select
returns an output element for every input element.
Whereas Enumerable.SelectMany
produces a variable number of output elements for each input element. This means that the output sequence may contain more or fewer elements than were in the input sequence.
Lambda expressions
passed to Enumerable.Select
must return a single item. Lambda expressions passed to Enumerable.SelectMany
must produce a child sequence. This child sequence may contain a varying number of elements for each element in the input sequence.
Example
class Invoice
{
public int Id { get; set; }
}
class Customer
{
public Invoice[] Invoices {get;set;}
}
var customers = new[] {
new Customer {
Invoices = new[] {
new Invoice {Id=1},
new Invoice {Id=2},
}
},
new Customer {
Invoices = new[] {
new Invoice {Id=3},
new Invoice {Id=4},
}
},
new Customer {
Invoices = new[] {
new Invoice {Id=5},
new Invoice {Id=6},
}
}
};
var allInvoicesFromAllCustomers = customers.SelectMany(c => c.Invoices);
Console.WriteLine(
string.Join(",", allInvoicesFromAllCustomers.Select(i => i.Id).ToArray()));
Output:
1,2,3,4,5,6
Enumerable.SelectMany
can also be achieved with a syntax-based query using two consecutive from
clauses:
var allInvoicesFromAllCustomers
= from customer in customers
from invoice in customer.Invoices
select invoice;
Sum
var numbers = new[] {1,2,3,4};
var sumOfAllNumbers = numbers.Sum();
Console.WriteLine(sumOfAllNumbers); //10
var cities = new[] {
new {Population = 1000},
new {Population = 2500},
new {Population = 4000}
};
var totalPopulation = cities.Sum(c => c.Population);
Console.WriteLine(totalPopulation); //7500
Skip
Skip will enumerate the first N items without returning them. Once item number N+1 is reached, Skip starts returning every enumerated item:
var numbers = new[] {1,2,3,4,5};
var allNumbersExceptFirstTwo = numbers.Skip(2);
Console.WriteLine(string.Join(",", allNumbersExceptFirstTwo.ToArray()));
//3,4,5
Take
This method takes the first n
elements from an enumerable.
var numbers = new[] {1,2,3,4,5};
var threeFirstNumbers = numbers.Take(3);
Console.WriteLine(string.Join(",", threeFirstNumbers.ToArray()));
//1,2,3
SequenceEqual
var numbers = new[] {1,2,3,4,5};
var sameNumbers = new[] {1,2,3,4,5};
var sameNumbersInDifferentOrder = new[] {5,1,4,2,3};
var equalIfSameOrder = numbers.SequenceEqual(sameNumbers);
Console.WriteLine(equalIfSameOrder); //True
var equalIfDifferentOrder = numbers.SequenceEqual(sameNumbersInDifferentOrder);
Console.WriteLine(equalIfDifferentOrder); //False
Reverse
var numbers = new[] {1,2,3,4,5};
var reversed = numbers.Reverse();
Console.WriteLine(string.Join(",", reversed.ToArray()));
//5,4,3,2,1
OfType
var mixed = new object[] {1,"Foo",2,"Bar",3,"Fizz",4,"Buzz"};
var numbers = mixed.OfType<int>();
Console.WriteLine(string.Join(",", numbers.ToArray()));
//1,2,3,4
Max
var numbers = new[] {1,2,3,4};
var maxNumber = numbers.Max();
Console.WriteLine(maxNumber); //4
var cities = new[] {
new {Population = 1000},
new {Population = 2500},
new {Population = 4000}
};
var maxPopulation = cities.Max(c => c.Population);
Console.WriteLine(maxPopulation); //4000
Min
var numbers = new[] {1,2,3,4};
var minNumber = numbers.Min();
Console.WriteLine(minNumber); //1
var cities = new[] {
new {Population = 1000},
new {Population = 2500},
new {Population = 4000}
};
var minPopulation = cities.Min(c => c.Population);
Console.WriteLine(minPopulation); //1000
Average
var numbers = new[] {1,2,3,4};
var averageNumber = numbers.Average();
Console.WriteLine(averageNumber);
// 2,5
This method calculates the average of enumerable of numbers.
var cities = new[] {
new {Population = 1000},
new {Population = 2000},
new {Population = 4000}
};
var averagePopulation = cities.Average(c => c.Population);
Console.WriteLine(averagePopulation);
// 2333,33
This method calculates the average of enumerable using delegated function.
Zip
var tens = new[] {10,20,30,40,50};
var units = new[] {1,2,3,4,5};
var sums = tens.Zip(units, (first, second) => first + second);
Console.WriteLine(string.Join(",", sums));
//11,22,33,44,55
Distinct
var numbers = new[] {1, 1, 2, 2, 3, 3, 4, 4, 5, 5};
var distinctNumbers = numbers.Distinct();
Console.WriteLine(string.Join(",", distinctNumbers));
//1,2,3,4,5
GroupBy
var persons = new[] {
new { Name="Fizz", Job="Developer"},
new { Name="Buzz", Job="Developer"},
new { Name="Foo", Job="Astronaut"},
new { Name="Bar", Job="Astronaut"},
};
var groupedByJob = persons.GroupBy(p => p.Job);
foreach(var theGroup in groupedByJob)
{
Console.WriteLine(
"{0} are {1}s",
string.Join(",", theGroup.Select(g => g.Name).ToArray()),
theGroup.Key);
}
//Fizz,Buzz are Developers
//Foo,Bar are Astronauts
Group invoices by country, generating a new object with the number of record, total paid, and average paid
var a = db.Invoices.GroupBy(i => i.Country)
.Select(g => new { Country = g.Key,
Count = g.Count(),
Total = g.Sum(i => i.Paid),
Average = g.Average(i => i.Paid) });
If we want only the totals, no group
var a = db.Invoices.GroupBy(i => 1)
.Select(g => new { Count = g.Count(),
Total = g.Sum(i => i.Paid),
Average = g.Average(i => i.Paid) });
If we need several counts
var a = db.Invoices.GroupBy(g => 1)
.Select(g => new { High = g.Count(i => i.Paid >= 1000),
Low = g.Count(i => i.Paid < 1000),
Sum = g.Sum(i => i.Paid) });
ToDictionary
Returns a new dictionary from the source IEnumerable
using the provided keySelector function to determine keys. Will throw an ArgumentException
if keySelector is not injective(returns a unique value for each member of the source collection.) There are overloads which allow one to specify the value to be stored as well as the key.
var persons = new[] {
new { Name="Fizz", Id=1},
new { Name="Buzz", Id=2},
new { Name="Foo", Id=3},
new { Name="Bar", Id=4},
};
Specifying just a key selector function will create a Dictionary<TKey,TVal>
with TKey
the return Type of the key selector, TVal
the original object Type, and the original object as the stored value.
var personsById = persons.ToDictionary(p => p.Id);
// personsById is a Dictionary<int,object>
Console.WriteLine(personsById[1].Name); //Fizz
Console.WriteLine(personsById[2].Name); //Buzz
Specifying a value selector function as well will create a Dictionary<TKey,TVal>
with TKey
still the return type of the key selector, but TVal
now the return type of the value selector function, and the returned value as the stored value.
var namesById = persons.ToDictionary(p => p.Id, p => p.Name);
//namesById is a Dictionary<int,string>
Console.WriteLine(namesById[3]); //Foo
Console.WriteLine(namesById[4]); //Bar
As stated above, the keys returned by the key selector must be unique. The following will throw an exception.
var persons = new[] {
new { Name="Fizz", Id=1},
new { Name="Buzz", Id=2},
new { Name="Foo", Id=3},
new { Name="Bar", Id=4},
new { Name="Oops", Id=4}
};
var willThrowException = persons.ToDictionary(p => p.Id)
If a unique key can not be given for the source collection, consider using ToLookup instead. On the surface, ToLookup behaves similarly to ToDictionary, however, in the resulting Lookup each key is paired with a collection of values with matching keys.
Union
var numbers1to5 = new[] {1,2,3,4,5};
var numbers4to8 = new[] {4,5,6,7,8};
var numbers1to8 = numbers1to5.Union(numbers4to8);
Console.WriteLine(string.Join(",", numbers1to8));
//1,2,3,4,5,6,7,8
Note that duplicates are removed from the result. If this is undesirable, use Concat
instead.
ToArray
var numbers = new[] {1,2,3,4,5,6,7,8,9,10};
var someNumbers = numbers.Where(n => n < 6);
Console.WriteLine(someNumbers.GetType().Name);
//WhereArrayIterator`1
var someNumbersArray = someNumbers.ToArray();
Console.WriteLine(someNumbersArray.GetType().Name);
//Int32[]
ToList
var numbers = new[] {1,2,3,4,5,6,7,8,9,10};
var someNumbers = numbers.Where(n => n < 6);
Console.WriteLine(someNumbers.GetType().Name);
//WhereArrayIterator`1
var someNumbersList = someNumbers.ToList();
Console.WriteLine(
someNumbersList.GetType().Name + " - " +
someNumbersList.GetType().GetGenericArguments()[0].Name);
//List`1 - Int32
Count
IEnumerable<int> numbers = new[] {1,2,3,4,5,6,7,8,9,10};
var numbersCount = numbers.Count();
Console.WriteLine(numbersCount); //10
var evenNumbersCount = numbers.Count(n => (n & 1) == 0);
Console.WriteLine(evenNumbersCount); //5
ElementAt
var names = new[] {"Foo","Bar","Fizz","Buzz"};
var thirdName = names.ElementAt(2);
Console.WriteLine(thirdName); //Fizz
//The following throws ArgumentOutOfRangeException
var minusOnethName = names.ElementAt(-1);
var fifthName = names.ElementAt(4);
ElementAtOrDefault
var names = new[] {"Foo","Bar","Fizz","Buzz"};
var thirdName = names.ElementAtOrDefault(2);
Console.WriteLine(thirdName); //Fizz
var minusOnethName = names.ElementAtOrDefault(-1);
Console.WriteLine(minusOnethName); //null
var fifthName = names.ElementAtOrDefault(4);
Console.WriteLine(fifthName); //null
SkipWhile
var numbers = new[] {2,4,6,8,1,3,5,7};
var oddNumbers = numbers.SkipWhile(n => (n & 1) == 0);
Console.WriteLine(string.Join(",", oddNumbers.ToArray()));
//1,3,5,7
TakeWhile
var numbers = new[] {2,4,6,1,3,5,7,8};
var evenNumbers = numbers.TakeWhile(n => (n & 1) == 0);
Console.WriteLine(string.Join(",", evenNumbers.ToArray()));
//2,4,6
DefaultIfEmpty
var numbers = new[] {2,4,6,8,1,3,5,7};
var numbersOrDefault = numbers.DefaultIfEmpty();
Console.WriteLine(numbers.SequenceEqual(numbersOrDefault)); //True
var noNumbers = new int[0];
var noNumbersOrDefault = noNumbers.DefaultIfEmpty();
Console.WriteLine(noNumbersOrDefault.Count()); //1
Console.WriteLine(noNumbersOrDefault.Single()); //0
var noNumbersOrExplicitDefault = noNumbers.DefaultIfEmpty(34);
Console.WriteLine(noNumbersOrExplicitDefault.Count()); //1
Console.WriteLine(noNumbersOrExplicitDefault.Single()); //34
Aggregate (fold)
Generating a new object in each step:
var elements = new[] {1,2,3,4,5};
var commaSeparatedElements = elements.Aggregate(
seed: "",
func: (aggregate, element) => $"{aggregate}{element},");
Console.WriteLine(commaSeparatedElements); //1,2,3,4,5,
Using the same object in all steps:
var commaSeparatedElements2 = elements.Aggregate(
seed: new StringBuilder(),
func: (seed, element) => seed.Append($"{element},"));
Console.WriteLine(commaSeparatedElements2.ToString()); //1,2,3,4,5,
Using a result selector:
var commaSeparatedElements3 = elements.Aggregate(
seed: new StringBuilder(),
func: (seed, element) => seed.Append($"{element},"),
resultSelector: (seed) => seed.ToString());
Console.WriteLine(commaSeparatedElements3); //1,2,3,4,5,
If a seed is omitted, the first element becomes the seed:
var seedAndElements = elements.Select(n=>n.ToString());
var commaSeparatedElements4 = seedAndElements.Aggregate(
func: (aggregate, element) => $"{aggregate}{element},");
Console.WriteLine(commaSeparatedElements4); //12,3,4,5,
ToLookup
var persons = new[] {
new { Name="Fizz", Job="Developer"},
new { Name="Buzz", Job="Developer"},
new { Name="Foo", Job="Astronaut"},
new { Name="Bar", Job="Astronaut"},
};
var groupedByJob = persons.ToLookup(p => p.Job);
foreach(var theGroup in groupedByJob)
{
Console.WriteLine(
"{0} are {1}s",
string.Join(",", theGroup.Select(g => g.Name).ToArray()),
theGroup.Key);
}
//Fizz,Buzz are Developers
//Foo,Bar are Astronauts
Join
class Developer
{
public int Id { get; set; }
public string Name { get; set; }
}
class Project
{
public int DeveloperId { get; set; }
public string Name { get; set; }
}
var developers = new[] {
new Developer {
Id = 1,
Name = "Foobuzz"
},
new Developer {
Id = 2,
Name = "Barfizz"
}
};
var projects = new[] {
new Project {
DeveloperId = 1,
Name = "Hello World 3D"
},
new Project {
DeveloperId = 1,
Name = "Super Fizzbuzz Maker"
},
new Project {
DeveloperId = 2,
Name = "Citizen Kane - The action game"
},
new Project {
DeveloperId = 2,
Name = "Pro Pong 2016"
}
};
var denormalized = developers.Join(
inner: projects,
outerKeySelector: dev => dev.Id,
innerKeySelector: proj => proj.DeveloperId,
resultSelector:
(dev, proj) => new {
ProjectName = proj.Name,
DeveloperName = dev.Name});
foreach(var item in denormalized)
{
Console.WriteLine("{0} by {1}", item.ProjectName, item.DeveloperName);
}
//Hello World 3D by Foobuzz
//Super Fizzbuzz Maker by Foobuzz
//Citizen Kane - The action game by Barfizz
//Pro Pong 2016 by Barfizz
GroupJoin
class Developer
{
public int Id { get; set; }
public string Name { get; set; }
}
class Project
{
public int DeveloperId { get; set; }
public string Name { get; set; }
}
var developers = new[] {
new Developer {
Id = 1,
Name = "Foobuzz"
},
new Developer {
Id = 2,
Name = "Barfizz"
}
};
var projects = new[] {
new Project {
DeveloperId = 1,
Name = "Hello World 3D"
},
new Project {
DeveloperId = 1,
Name = "Super Fizzbuzz Maker"
},
new Project {
DeveloperId = 2,
Name = "Citizen Kane - The action game"
},
new Project {
DeveloperId = 2,
Name = "Pro Pong 2016"
}
};
var grouped = developers.GroupJoin(
inner: projects,
outerKeySelector: dev => dev.Id,
innerKeySelector: proj => proj.DeveloperId,
resultSelector:
(dev, projs) => new {
DeveloperName = dev.Name,
ProjectNames = projs.Select(p => p.Name).ToArray()});
foreach(var item in grouped)
{
Console.WriteLine(
"{0}'s projects: {1}",
item.DeveloperName,
string.Join(", ", item.ProjectNames));
}
//Foobuzz's projects: Hello World 3D, Super Fizzbuzz Maker
//Barfizz's projects: Citizen Kane - The action game, Pro Pong 2016
Cast
Cast
is different from the other methods of Enumerable
in that it is an extension method for IEnumerable
, not for IEnumerable<T>
. Thus it can be used to convert instances of the former into instances of the later.
This does not compile since ArrayList
does not implement IEnumerable<T>
:
var numbers = new ArrayList() {1,2,3,4,5};
Console.WriteLine(numbers.First());
This works as expected:
var numbers = new ArrayList() {1,2,3,4,5};
Console.WriteLine(numbers.Cast<int>().First()); //1
Cast
does not perform conversion casts. The following compiles but throws InvalidCastException
at runtime:
var numbers = new int[] {1,2,3,4,5};
decimal[] numbersAsDecimal = numbers.Cast<decimal>().ToArray();
The proper way to perform a converting cast to a collection is as follows:
var numbers= new int[] {1,2,3,4,5};
decimal[] numbersAsDecimal = numbers.Select(n => (decimal)n).ToArray();
Empty
To create an empty IEnumerable of int:
IEnumerable<int> emptyList = Enumerable.Empty<int>();
This empty IEnumerable
Enumerable.Empty<decimal>() == Enumerable.Empty<decimal>(); // This is True
Enumerable.Empty<int>() == Enumerable.Empty<decimal>(); // This is False
ThenBy
ThenBy
can only be used after a OrderBy
clause allowing to order using multiple criteria
var persons = new[]
{
new {Id = 1, Name = "Foo", Order = 1},
new {Id = 1, Name = "FooTwo", Order = 2},
new {Id = 2, Name = "Bar", Order = 2},
new {Id = 2, Name = "BarTwo", Order = 1},
new {Id = 3, Name = "Fizz", Order = 2},
new {Id = 3, Name = "FizzTwo", Order = 1},
};
var personsSortedByName = persons.OrderBy(p => p.Id).ThenBy(p => p.Order);
Console.WriteLine(string.Join(",", personsSortedByName.Select(p => p.Name)));
//This will display :
//Foo,FooTwo,BarTwo,Bar,FizzTwo,Fizz
Range
The two parameters to Range
are the first number and the count of elements to produce (not the last number).
// prints 1,2,3,4,5,6,7,8,9,10
Console.WriteLine(string.Join(",", Enumerable.Range(1, 10)));
// prints 10,11,12,13,14
Console.WriteLine(string.Join(",", Enumerable.Range(10, 5)));
Left Outer Join
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}
public static void Main(string[] args)
{
var magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
var terry = new Person { FirstName = "Terry", LastName = "Adams" };
var barley = new Pet { Name = "Barley", Owner = terry };
var people = new[] { magnus, terry };
var pets = new[] { barley };
var query =
from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj.DefaultIfEmpty()
select new
{
person.FirstName,
PetName = subpet?.Name ?? "-" // Use - if he has no pet
};
foreach (var p in query)
Console.WriteLine($"{p.FirstName}: {p.PetName}");
}
Repeat
Enumerable.Repeat
generates a sequence of a repeated value. In this example it generates “Hello” 4 times.
var repeats = Enumerable.Repeat("Hello", 4);
foreach (var item in repeats)
{
Console.WriteLine(item);
}
/* output:
Hello
Hello
Hello
Hello
*/