LINQ via C# 3.0 Chapter – C# 3.0 Language Features © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel New C# 3.0 Language Features • Why more language features? • Increased developer productivity – Implicit typing, initializers, automatic properties, anonymous types • Extensibility concepts – Extension methods, partial methods • Functional programming concepts – Lambda expressions, expression trees • Support for integrated queries (LINQ) – Language query operators © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Automatic Properties public class Person { private int id; private string name; public class Person { public string Name { Becomes public int Id { get; set; get { return id; } } set { id = value; } public int Id { } get; set; public string Name { get { return name; } } set { name = value; } } } } © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Where’s The Magic? • Compiler generated code (from Reflector: http://tinyurl.com/9hwl7) public class Person { private int k BackingField; private string k BackingField; public int Id { get { return this.k BackingField; } set { this.k BackingField = value; } } public string Name { get { return this.k BackingField; } set { this.k BackingField = value; } } } © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Feature Notes • Read-only properties can be emulated by specifying private set; – This is not the equivalent of a readonly field! – It can be modified from within the class • The backing field is inaccessible directly • Property logic cannot be customized for one of the accessors © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Object Initializers Person p = new Person( 2, “John Doe”); Person p = new Person { //Or: Id = 2, Becomes Name = “John Doe” Person p =new Person(); }; p.Id = 2; p.Name = “John Doe”; © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Where’s The Magic? • Compiler-generated code: Person g initLocal0 = new Person(); g initLocal0.Id = 2; g initLocal0.Name = "John Doe"; Person p = g initLocal0; © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Feature Notes • Non default constructors can be called new Person(“John Doe”) { Id = } • Why an excessive local variable? – Emulate atomic construction and assignment – Other threads can’t see a partially assigned object • Some properties have severe side effects – E.g., FileSystemWatcher.Enabled © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Collection Initializers List nums = new List(); nums.Add(5); nums.Add(3); nums.Add(20); List nums = new List { 5, 3, 20 Becomes }; Dictionary dict Dictionary dict= = new Dictionary new Dictionary(); dict.Add(“A”, 1); dict.Add(“B”, 2); { { “A”, }, Becomes { “B”, } }; © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel What’s The Magic? • Compiler-generated code: List g initLocal1 = new List(); g initLocal1.Add(5); g initLocal1.Add(3); g initLocal1.Add(20); List nums = g initLocal1; Dictionary g initLocal2 = new Dictionary(); g initLocal2.Add("A", 1); g initLocal2.Add("B", 2); Dictionary dict = g initLocal2; © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Where’s The Magic? • Compiler-generated code (edited): private static string Converter(int i) { return i.ToString(); } private static MyConverter Cached; //My code: if ( Cached == null) { Cached = new MyConverter( Converter); } string s = Cached(5); © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Captured Variables • Interesting patterns arise when we have closures, including captured variables: void Foo() { bool stop = false; //Should be volatile Thread t = new Thread(delegate() { while(!stop) //Do some work }); t.Start(); Console.ReadKey(); stop = true; t.Join(); } © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Where’s The Magic? • How can the variable be shared? – Through a class! Compiler generated code (edited): private sealed class TheClass { public bool stop; //=false public void TheMethod() { while (!stop) //Do some work } } //My code: TheClass c = new TheClass(); Thread t = new Thread(c. TheMethod); t.Start(); Console.ReadKey(); c.stop = true; t.Join(); © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel C# 3.0 – Lambda Expressions • A concise, functional syntax for anonymous methods: //Defined in System.Core.dll public delegate TResult Func(T arg); Func converter = x => x.ToString(); string s = converter(5); • Compiles to the same as an anonymous method © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Lambda Expressions Func identity = x => x; Func fifteen = () => 15; Func mul = (x,y) => x*y; //Currying: Func mulByFive = x => mul(x,5); Func square = x => mul(x,x); //More explicit: Func add = (int x,int y) => x+y; var fn = x => x; //Doesn’t compile © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Statement Lambdas Action print = i => Console.WriteLine(i); Action printIfEven = i => { if (i % == 0) Console.WriteLine(i + “ is even”); }; Predicate filter = i => { if (i % == && i < 15) return true; if (i > 160) return false; return true; }; © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Lambdas Simplify Code static class Extensions { public static List Filter( this List list, Predicate filter) { List filtered = new List(); list.ForEach(i => { if (filter(i)) filtered.Add(i); }); return filtered; } } List numbers = new List { 1,2,3,4 }; numbers.Filter(i => i%2==0) ForEach(Console.WriteLine); © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Feature Notes • 100-line lambdas are best moved to a method • If you need to reuse the code elsewhere, use a method • Beware of capturing side-effects: for (int i = 0; i < 100; ++i) { ThreadPool.QueueUserWorkItem((o) => { Thread.Sleep(100); Console.WriteLine(i); }); //Prints 100, 100 times } //Fix by declaring int copy=i; //inside the loop, and using copy © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Expression Trees • An expression lambda can be captured as an expression tree – Code = Data • The expression tree can be analyzed at runtime Expression square = x => x*x; Func compiled = square.Compile(); Console.WriteLine(compiled(5)); © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Where’s The Magic? • The tree is generated by the compiler: ParameterExpression x, y; Expression mul = Expression.Lambda( Expression.Multiply( x = Expression.Parameter(typeof(int),”x”), y = Expression.Parameter(typeof(int),”y”) ), new ParameterExpression[] { x, y } ); © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel The Expression Tree • At runtime, the tree appears as follows: Expression BinaryExpression ExpressionType=Multiply Type=Int32 ParameterExpression Name=x, Type=Int32 ParameterExpression Name=y, Type=Int32 © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Feature Notes • Expression trees turn code into data • They can be used to dynamically analyze expressions and provide different behavior – LINQ Providers use this extensively ã Expression Tree Visualizer (MSDNđ sample) http://tinyurl.com/ExpTreeVis © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Review So Far • Functional programming enablers ã Lambda Expressions ã Expression Trees â Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel Language Query Operators • C# 3.0 includes language query operators – Facilitate integrated queries on all kinds of data – Remember the LINQ challenge: Accessing and integrating non-OO information, while abstracting away its source – Query operators form the abstraction – More on this in the LINQ chapters (3-7) var query = from cust in customers //The source where cust.Balance > orderby cust.Name select new { cust.Name, cust.Balance }; query.ToList().ForEach(cust => SendAppreciationNote(cust.Name,14-18 Baruch Hirsch St Bnei Brak 51202 Israel cust.Balance); © Copyright SELA Software & Education Labs Ltd Chapter Summary • Increased developer productivity – Implicit typing, initializers, automatic properties, anonymous types • Extensibility concepts – Extension methods, partial methods • Functional programming concepts – Lambda expressions, expression trees • Support for integrated queries (LINQ) – Language query operators • C# 3.0 Language Specification: http://tinyurl.com/baoh8 © Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel ... customization: – Intra-assembly, compile-time only © Copyright SELA Software & Education Labs Ltd 1 4-1 8 Baruch Hirsch St Bnei Brak 5 120 2 Israel Review So Far • Extensibility features • Extension... List { 1 ,2, 3,4 }; numbers.Filter(i => i %2= =0) ForEach(Console.WriteLine); © Copyright SELA Software & Education Labs Ltd 1 4-1 8 Baruch Hirsch St Bnei Brak 5 120 2 Israel Feature Notes • 100-line lambdas... =new Person(); }; p.Id = 2; p.Name = “John Doe”; © Copyright SELA Software & Education Labs Ltd 1 4-1 8 Baruch Hirsch St Bnei Brak 5 120 2 Israel Where’s The Magic? • Compiler-generated code: Person