Last active
December 25, 2015 20:49
-
-
Save joladev/7038347 to your computer and use it in GitHub Desktop.
LINQ 101
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Getting some cruft out of the way | |
public class le{ | |
// Set up a Person class for use in examples. | |
public class Person{ public string Name { get; set; } } | |
public static void Main(string[] args){ | |
// A gentle introduction to LINQ, language integrated queries, | |
// in C#. To start off, let's do some disambiguation. | |
// This is a lambda expression | |
// s => s == "hello" | |
// These are extension methods exposed by LINQ | |
// Select, Where, GroupBy, OrderBy, etc | |
// This is query syntax, a syntactic sugar | |
// over the LINQ extension methods. | |
// from l | |
// where l.name == "ada" | |
// select l | |
// | |
// For this tutorial, we'll be focusing on LINQ | |
// methods directly, using lambda expressions. | |
// | |
// Data for examples. | |
var persons = [ | |
new Person() { Name="Ada" }, | |
new Person() { Name="Haskell" } | |
]; | |
// | |
// SELECT | |
// | |
// We begin by taking a look at "select". | |
// This is an extension method which attaches | |
// itself to lists and listlike things (IEnumerable). | |
// | |
// It corresponds to "select" in SQL and "project" | |
// in relational algebra. Here are some examples: | |
var names = persons.Select(p => p.Name); | |
// => ["Ada", "Haskell"] | |
var uppers = names.Select(n => n.ToUpperCase()); | |
// => ["ADA", "HASKELL"] | |
// LINQ methods lend themselves well to chaining, | |
// as each method returns a modified version of | |
// its input. Combining the two lines from above: | |
var combo = persons.Select(p => p.Name) | |
.Select(n => n.ToUpperCase()); | |
// => ["ADA, "HASKELL"] | |
// You can also do mostly pointless things like | |
var wtf = person.Select(p => "Tesla"); | |
// => ["Tesla", "Tesla"] | |
// Essentially, select, and all the other LINQ | |
// methods, act as transformations upon data. | |
// Select takes a lambda expression (or delegate) | |
// and applies this for each value in the list. | |
// On the first pass, p is "Ada". When we apply | |
// our transformation, this is replaced with | |
// "Tesla". Select continues to iterate through | |
// the entire list, applying the lambda expression | |
// on each value and gathering the results into | |
// a new list, which it returns. | |
// This means LINQ doesn't change the list you | |
// call it on. It always returns new lists. This | |
// has some nice implications for concurrency | |
// and parallelism and tends to lead to more | |
// expressive code. | |
// | |
// WHERE | |
// | |
// Moving on from projections, let's take a look | |
// at the filtering method. It corresponds to | |
// where in SQL and select in relational algebra. | |
var ada = persons.Where(p => p.Name == "Ada"); | |
// => ["Ada"] | |
// Where takes a lambda that returns a boolean. | |
// This is commonly known as a "predicate". | |
// Any boolean expression serves as a predicate. | |
// Where can also be chained with Select. | |
var adaString = persons.Select(p => p.Name) | |
.Where(s => s == "Ada"); | |
// => ["Ada"] | |
var haskellString = persons.Select(p => p.Name) | |
.Where(s => s != "Ada"); | |
// => ["Haskell"] | |
// | |
// Brief interlude: CLOSURES | |
// | |
// C# also handles closures for lambda expressions. | |
// This is something that you probably have used, | |
// and normally "just works". But knowledge is | |
// power, so let's take a look. | |
var target = "Haskell"; | |
var haskell = persons.Where(p => p.Name == target); | |
// => ["Haskell"] | |
// So what's so impressive about that? | |
// If we take a closer look at the lambda. | |
// p => p.Name == target | |
// There are two variables involved: p and target. | |
// p is supplied through the anonymous function, | |
// or delegate, parameter. It is bound to the | |
// scope of the lambda in the way we are used to. | |
// But how does target get in there? | |
// END | |
}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment