Projection Operations
Projection operations transform objects into new forms typically consisting of only properties subsequently used.
It constructs a new type from each object. A property can be projected prior to performing a mathematical function on it. Projection can occur with no change to the original object.
The query operator methods used to perform projection follow: Select and SelectMany. The Select method projects values based on a transform function. It uses the following syntax:
public static IEnumerable<TResult> Select<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, TResult> selector )
Review an example below:
List<string> terms = new List<string>() { "your", "purple", "fox", "all", "day", "all", "night" }; var query = from term in terms select term.Substring(0, 1); foreach (string q in query) Console.WriteLine(q);
The SelectMany method projects value sequences based on a transform function which it then forms into a single sequence. It uses the following syntax:
public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector )
Review an example below:
List<string> lyrics = new List<string>() { "all the critics love you in New York", "all I wanna do is Dance" }; var query = from lyric in lyrics from term in lyric.Split(' ') select term; foreach (string q in query) Console.WriteLine(q);
SEPARATING FUNCTION
Both Select and SelectMany yield a result value(s) from source values, however, Select produces a single result for each source value. This results in a collection of elements with the same quantity of elements as its source collection. Compare this to SelectMany yielding one result containing concatenated sub-collections from each source value.
FORMS
Use the select clause to perform a wide variety tasks. Review some of the many ways to use select below:
class SelectExample { // class definitions public class Player { public string GivenNm { get; set; } public string SurNm { get; set; } public int ID { get; set; } public List<int> Rankings; public ContactInfo GetContactInfo(SelectExample app, int id) { ContactInfo cInfo = (from ci in app.contactList where ci.ID == id select ci) .FirstOrDefault(); return cInfo; } public override string ToString() { return GivenNm + " " + SurNm + ":" + ID; } } public class ContactInfo { public int ID { get; set; } public string Email { get; set; } public string Mobile { get; set; } public override string ToString() { return Email + "," + Mobile; } } public class RankInfo { public double Average { get; set; } public int ID { get; set; } } // primary data source List<Player> players = new List<Player>() { new Player {GivenNm="Mike", SurNm="Smith", ID=111, Rankings= new List<int>() {110, 132, 145, 99}}, new Player {GivenNm="Stacy", SurNm="Thompson", ID=112, Rankings= new List<int>() {55, 63, 45, 77}}, new Player {GivenNm="Bernard", SurNm="Wright", ID=113, Rankings= new List<int>() {71, 84, 75, 99}}, new Player {GivenNm="Jermaine", SurNm="Jackson", ID=114, Rankings= new List<int>() {70, 88, 89, 90}}, }; // contact info data source List<ContactInfo> contactList = new List<ContactInfo>() { new ContactInfo {ID=111, Email="msmitty@Contoso.com", Mobile="555-505-0101"}, new ContactInfo {ID=112, Email="stacyt@Contoso.com", Mobile="555-505-0248"}, new ContactInfo {ID=113, Email="thenard@Contoso.com", Mobile="555-505-1440"}, new ContactInfo {ID=114, Email="jermj@Contoso.com", Mobile="555-505-0231"} }; static void Main(string[] args) { SelectExample app = new SelectExample(); // make a filtered sequence of unmodified Players IEnumerable<Player> playerQueryOne = from player in app.players where player.ID > 111 select player; Console.WriteLine("First Query: select range_variable"); foreach (Player p in playerQueryOne) { Console.WriteLine(p.ToString()); } // Make a filtered sequence of elements containing // only one property of each Player. IEnumerable<String> playerQueryTwo = from player in app.players where player.ID > 111 select player.SurNm; Console.WriteLine("\r\n playerQueryTwo: select range_variable.Property"); foreach (string p in playerQueryTwo) { Console.WriteLine(p); } // Make a filtered sequence of objects produced by // a method call on each Player. IEnumerable<ContactInfo> playerQueryThree = from player in app.players where player.ID > 111 select player.GetContactInfo(app, player.ID); Console.WriteLine("\r\n playerQueryThree: select range_variable.Method"); foreach (ContactInfo ci in playerQueryThree) { Console.WriteLine(ci.ToString()); } // Make a filtered sequence of ints from // the internal array inside each Player. IEnumerable<int> playerQueryFour = from player in app.players where player.ID > 111 select player.Rankings[0]; Console.WriteLine("\r\n playerQueryFour: select range_variable[index]"); foreach (int i in playerQueryFour) { Console.WriteLine("1st rank = {0}", i); } // Make a filtered sequence of doubles; // the expression result. IEnumerable<double> playerQueryFive = from player in app.players where player.ID > 111 select player.Rankings[0] * 1.1; Console.WriteLine("\r\n playerQueryFive: select expression"); foreach (double d in playerQueryFive) { Console.WriteLine("Adjusted 1st ranking = {0}", d); } // Produce a filtered sequence of doubles that are // the result of a method call. IEnumerable<double> playerQuerySix = from player in app.players where player.ID > 111 select player.Rankings.Average(); Console.WriteLine("\r\n playerQuerySix: select expression2"); foreach (double d in playerQuerySix) { Console.WriteLine("Average = {0}", d); } // Make a filtered sequence of anonymous types // containing only two properties from each Player. var playerQuerySeven = from player in app.players where player.ID > 111 select new { player.GivenNm, player.SurNm }; Console.WriteLine("\r\n playerQuerySeven: select new anonymous type"); foreach (var item in playerQuerySeven) { Console.WriteLine("{0}, {1}", item.SurNm, item.GivenNm); } // Make a filtered sequence of named objects containing // a method return value and a property from each Player. IEnumerable<RankInfo> playerQueryEight = from player in app.players where player.ID > 111 select new RankInfo { Average = player.Rankings.Average(), ID = player.ID }; Console.WriteLine("\r\n playerQueryEight: select new named type"); foreach (RankInfo ri in playerQueryEight) { Console.WriteLine("ID = {0}, Average = {1}", ri.ID, ri.Average); } // Make a filtered sequence of players from a contact list // and who average over 60. IEnumerable<ContactInfo> playerQueryNine = from player in app.players where player.Rankings.Average() > 60 join ci in app.contactList on player.ID equals ci.ID select ci; Console.WriteLine("\r\n playerQueryNine: select result of join clause"); foreach (ContactInfo ci in playerQueryNine) { Console.WriteLine("ID = {0}, Email = {1}", ci.ID, ci.Email); } Console.WriteLine("Press a key to continue."); Console.ReadKey(); } }