280 likes | 384 Views
From (Visitor) to LINQ. LINQ (this is where we ends in this presentation):. var query = from a in accounts.TestData where a.Balance > 1e6 select a ; foreach (Account a in query) Console.WriteLine ( a.Balance );. Operations on a container without Visitor. //Doubling evens
E N D
From (Visitor) to LINQ LINQ (this is where we ends in this presentation): var query = from a in accounts.TestData where a.Balance > 1e6 select a; foreach(Account a in query) Console.WriteLine(a.Balance);
Operations on a container without Visitor //Doubling evens for(int i = 0; i < con1.N; i++) { if(con1.Get(i) % 2 == 0) con1.Update(i, con1.Get(i) * 2); } //Doubling all for(int i = 0; i < con1.N; i++){ con1.Update(i, con1.Get(i) * 2); } //Increasing small ones by one for(int i = 0; i < con1.N; i++){ if(con1.Get(i) < 10) con1.Update(i, con1.Get(i) + 1); }
Visitor in POJO(Plain Old Java Objects) interface Visitor { public int visit(MyInteger number);}interface Visitable { public int accept(Visitor visitor);}class MyInteger implements Visitable { private int value; MyInteger(int i) { this.value = i; } public int accept(Visitor visitor) { return visitor.visit(this); } public int getValue() { return value; }} Can implement selection criteria here
class SubtractVisitor implements Visitor { int value; public SubtractVisitor(int value) { this.value = value; } public int visit(MyInteger i) { System.out.println("Subtract integer"); return (i.getValue() - value); } }
Visitor implemented with delegates ModifyElement and CheckElement are delegates public class Accounts { private List<Account> TestData { get; set; } public Accounts(){ TestData = new List<Account>(); TestData.Add(new Account { Balance = 2222 }); TestData.Add(new Account { Balance = 22222 }) …. More test data} public void ModifyAll(ModifyElement f) {//Applies f to all elements in the container foreach (Account a in TestData) f(a); } public void ModifySome(ModifyElement f, CheckElement p) { //Applies f only to elements in the containerthat satisfy p foreach (Account a in TestData) if (p(a)) f(a);} }
The delegates public delegate boolCheckElement(Account e); public delegate Account ModifyElement(Account e);
Simple implementation • Just a class with operations with an appropriate signature public class AccountOperations { public Account PrintBalance(Account a) { Console.WriteLine(a.Balance); return null; } public Account DoubleBalance(Account a) { a.Balance *= 2; return a; } public Account ClearBalance(Account a) { a.Balance = 0f; return a; } public bool IsBigAccount(Account a) { return a.Balance > 1e6 && a.Balance <= 1e7; } ….. }
Driver Accounts accounts = new Accounts(); AccountOperations oper = new AccountOperations(); Console.WriteLine("TestData: "); ModifyElement print = oper.PrintBalance; accounts.ModifyAll(print); Console.WriteLine("Write big accounts"); CheckElement bigAccount = oper.IsBigAccount; accounts.ModifySome(print, bigAccount); Console.WriteLine("Clear small accounts"); CheckElement small = oper.IsSmallAccount; ModifyElement clear = oper.ClearBalance; accounts.ModifySome(clear, small); accounts.ModifyAll(print);
Use anonymous delegates • Given following delegate and method: • delegate int MyDelegate(int n); • void MyMethod(MyDelegate f){...} • Example on syntax for implementing delegate method: • MyDelegate doubleUp=delegate(int n){return 2*n;}; • MyMethod(doubleUp); • or shorter: • MyMethod(delegate(int n){return 2*n;}); • This is called inline implementation
Exercise • Rewrite delegate methods (Even, Double, LessThan10, etc.) in visitor example to use anonymous delegates. • Consider where it is (not) a good idea to use inline implementation
Driver with Anonymous delegate Console.WriteLine("TestData: "); ModifyElement print = delegate(Account a) { Console.WriteLine(a.Balance); return null; }; accounts.ModifyAll(print); Console.WriteLine("Write big accounts"); accounts.ModifySome(print, delegate(Account a) { return a.Balance > 1e6 && a.Balance <= 1e7; } ); The Print delegate is not inline as it is used multiple times
Lamda expression • Another way of defining anonymous methods // finds x’s bigger than 5 Predicate myPredicate = x=>x>5 myList.FindAll(myPredicate); //or myList.FindAll (x=>x>5); How to pronounce ”=>”: • Anders Hejlsberg: I usually read the => operator as "becomes" or "for which". For example,Func f = x => x * 2;Func test = c => c.City == "London";reads as "x becomes x * 2" and "c for which c.City equals London"
Lamda expression ModifyElement print = a=> { Console.WriteLine(a.Balance); return null; }; accounts.ModifyAll(print); Console.WriteLine("Write big accounts"); accounts.ModifySome(print, a=>a.Balance > 1e6 && a.Balance <= 1e7; );
Extention methods • It is possible to extend methods to a class without using inheriance • In fact, you might even extend a sealed class • This is done by using extention methods. • An extension method is a static method in a static class • By adding ‘this classname’ to the parameterlist, it becomes an extention method to classname
Example static class ExtensionEx { public static void WriteToConsole(this string s) { Console.WriteLine(s); } } Use: String s = "Hello"; s.WriteToConsole(); Is this really OO? Yes, it is just another way to write ExtentionEx.WriteToConsole(s);
Extension methods are the base of linq • Sample implementation of Where public static IEnumerable < TSource > Where < TSource > ( this IEnumerable < TSource > source, Func < TSource, bool > predicate) { foreach(TSource item in source) if (predicate(item)) yield return item; } yield: Start to return elements in a collection before all elements are known
Formula 1, ex1 • Using the delegates, anonymious methods and predicates IEnumerable < Racer > brazilChampions = Formula1.GetChampions(). Where(r = > r.Country == “Brazil”). OrderByDescending(r = > r.Wins). Select(r = > r); foreach (Racer r in brazilChampions) { Console.WriteLine(“{0:A}”, r); }
Exercise • Implement ‘Where’ and ‘Select’ in visitor example. • ”Where” has the same role as ”CheckElement” • ”Select” has the same role as ”ModifyElement”
Extention Methods (Where and Select) staticclassExtentions { publicstaticIEnumerable<int> Where(thisContainer source, Func<int, bool> predicate) { for (int i = 0; i < source.N; i++) { int item =source.Get(i); if (predicate(item)) yieldreturn item; } } publicstaticIEnumerable<int> Select(thisIEnumerable<int> source, Func<int, int> predicate) { foreach(int item in source) yieldreturn predicate(item); } }
Double all evens foreach (intiincon1 .Where(x => x % 2 == 0) .Select(r => r * 2) { Console.WriteLine(i); }
Anonymous types • Partly from MSDN: • Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. • The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler. • You create anonymous types by using the new operator together with an object initializer • The vartype is telling that it is an anonymous type var v = new { Amount = 108, Message = "Hello" }; Console.WriteLine(v.Amount+ v.Message);
Anonymous types • Partly from MSDN: • Anonymous types contain one or more public read-only properties. • That means that if you change a property value, you will get a new type. • No other kinds of class members, such as methods or events, are valid. • The expression that is used to initialize a property cannot be null, an anonymous function, or a pointer type. • The most common scenario is to initialize an anonymous type with properties from another type. • If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them. • You must provide a name for a property that is being initialized with an expression, as shown in the previous slide.
Anonymous types • Partly from MSDN: • The most common scenario is to initialize an anonymous type with properties from another type. • In the following example, assume that a class exists that is named Product. • Class Product includes Color and Price properties, together with other properties that you are not interested in. • Variable products is a collection of Product objects. • The anonymous type declaration starts with the new keyword. The declaration initializes a new type that uses only two properties from Product. • This causes a smaller amount of data to be returned in the query. • The names of the properties of the anonymous type are Color and Price.
Example (using LINQ) • From MSDN: var productQuery = fromprod in products selectnew { prod.Color, prod.Price }; foreach(var v in productQuery) { Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price); }
Formula 1, ex2 • LINQ: var query = from r in Formula1.GetChampions() where r.Country == “Brazil” orderby r.Wins descending select r; foreach (Racer r in query) { Console.WriteLine(“{0:A}”, r); } Compare this to Formula 1, ex1
Another example of simple LinqMore in next presentation var query = from a in accounts.TestData where a.Balance > 1e6 select a; foreach(Account a in query) Console.WriteLine(a.Balance);