Saturday, October 8, 2011

C Sharp By Example 4

C# Command Interpreter

< Prev  1 2 3 4 Next >

The interpreter method is embedded in an object from which we want to call instance methods from the command line even though the method is in another dll. This will let us run another method on the object from the command line.
/// Command interpreter for an object.  This allows methods to be called from the command line interactively.
/// All methods take a TextWriter as the first object to allow feedback.
/// Used with the Wizard front end.
/// </summary>
/// <param name="textWriter">For web apps this is "Response.Out", for Console use "Console.Out"</param>
/// <param name="args">arguments to method call</param>
public void Command(TextWriter textWriter, string[] args) {
 object[] param = new object[args.Length];
 param[0] = textWriter; //args[0] is the name of the method, so we can overwrite
 for(int i=1;i<args.Length;i++) { //load all the args into rest of param array
  param[i] = args[i];
 }
 MethodInfo methodInfo = this.GetType().GetMethod(args[0]);//try to get method
 if(methodInfo != null) { //invoke if successful
  methodInfo.Invoke(this,param);
 } else {
  textWriter.WriteLine(String.Format("unknown command \"\"","args[0]"));
 }
}
The Wizard front end creates an object from another dll, maybe inside a web application dll and calls the "Command" method.
using System;
namespace Wizard {
 class Wizard {
  /// 
  /// Invokes methods on objects in a dll (use config instead of hard coded path)
  /// 
  [STAThread]
  static void Main(string[] args) {
   object o = Activator.CreateInstanceFrom(@"C:\workfiles\SurveyDirector\src\SurveyDirector\bin\SurveyDirector.dll", "SurveyDirector.Admin.Operations").Unwrap();
   o.GetType().GetMethod("Command").Invoke(o,new object[]{Console.Out,args});
  }
 }
}
Methods to be invoke look something like this. Note this method can be called in a web context or from the command line.
using System;
using System.IO;
using System.Net;
using System.Reflection;            

namespace SurveyDirector.Admin {
public class Operations : System.Web.UI.Page {
...
public void LoadGroup(TextWriter textWriter, string ingroup) {
 ArrayList groups = new ArrayList();
 ...
 foreach(string group in groups) {
  textWriter.Write("
Loading group, \""+group+"\"");
  textWriter.Flush();
  Group.LoadFromDataDirectory(group,textWriter);
  textWriter.Flush();
  }
}
...
The following command will create an Operations object and invoke the "LoadGroup" method and pass "Baseline" as an argument:
c:\workfiles\Wizard\bin\Debug> Wizard.exe LoadGroup Baseline
< Prev  1 2 3 4 Next >

C Sharp by Example 3

C# Threading

< Prev  1 24  Next > 

  1. Simple multithreaded example in c#. The method passed as the ThreadStart delegate can have no arguments and must return void.
    using System;
    using System.Threading;
    
    public class ThreadTest {
     public class MyJob {
      public int repetitions=1;
      public void runme() {
       for(int i=0;i<repetitions;i++) {
        Thread.Sleep(1000);
          Console.WriteLine(Thread.CurrentThread.Name);
       }
      }
     }
     
        public static void Main(string[] args) {
     MyJob myJob = new MyJob();
     myJob.repetitions=3;
     Thread thread = new Thread(new ThreadStart(myJob.runme));
     thread.Name = "first";
            thread.Start();
     
     MyJob myJob2 = new MyJob();
     myJob2.repetitions=5;
     Thread thread2 = new Thread(new ThreadStart(myJob2.runme));
     thread2.Name = "second";
            thread2.Start();
        }
    }
    This produces
    first
    second
    first
    second
    first
    second
    second
    second
  2. Concurrency When two threads change the same data, bad things(tm) can happen. In the following example two threads increment and then decrement a global variable. In C# incrementing and decrementing are not necessarily atomic.
    using System;
    using System.Threading;
    
    public class ThreadTest2 {
     public class MyJob {
      public static int counter = 0;
      public int repetitions=100000000;
      public void runme() {
       for(int i=0;i<repetitions;i++) {
        counter++;
        counter--;
       }
       Console.WriteLine(Thread.CurrentThread.Name+": "+counter);
       
      }
     }
     
        public static void Main(string[] args) {
     MyJob myJob = new MyJob();
     Thread thread = new Thread(new ThreadStart(myJob.runme));
     thread.Name = "first";
            
     MyJob myJob2 = new MyJob();
     Thread thread2 = new Thread(new ThreadStart(myJob2.runme));
     thread2.Name = "second";
            
     thread.Start();
     thread2.Start();
        }
    }
    The results can be:
    first: 0
                second: 0
    or sometimes
    first: 1
                second: 0
    We can never be sure of the outcome. We can overcome this in several ways.
  3. Using Threading.Interlocked methods. Using Threading.Interlocked.Increment the CLR will guarentee an atomic operation. Another interesting method in the namespace is "Exchange()" which swaps two values atomically.
    public class MyJob {
     public static int counter = 0;
     public int repetitions=100000000;
     public void runme() {
      for(int i=0;i<repetitions;i++) {
       System.Threading.Interlocked.Increment(ref i);
       System.Threading.Interlocked.Decrement(ref i);
      }
      Console.WriteLine(Thread.CurrentThread.Name+": "+counter);
      
     }
    }
    The results will be:
    first: 0
                second: 0
  4. Using "lock()" to synchronize lock() takes an object as the argument. In this example we can use "this" since both threads are using the same "MyJob" instance. In static functions you can use the "type" object, e.g., "lock(typeof(Util))" to synchronize.
    public class MyJob {
     public static int counter = 0;
     public int repetitions=100000000;
     public void runme() {
      lock(this) {
         for(int i=0;i<repetitions;i++) {
       counter++;
       counter--;
         }
      }
      Console.WriteLine(Thread.CurrentThread.Name+": "+counter);
      
     }
    }
    
  5. The Synchronization attribute can be used.This locks the entire object - everything is single access. Note the object must descend from ContextBoundObject.
    [System.Runtime.Remoting.Contexts.Synchronization]
    public class MyJob: ContextBoundObject {
     public static int counter = 0;
     public int repetitions=100000000;
     public void runme() {
      for(int i=0;i<repetitions;i++) {
       counter++;
       counter--;
      }
      Console.WriteLine(Thread.CurrentThread.Name+": "+counter);
      
     }
    }
  6. Example of using Join() Join() hitches the fate of a thread to the current thread. Execution of the calling thread will wait until the callee's process completes. In this example we Join on a thread that takes 2 seconds to complete, then Join on a second that still has 2 seconds to go.
    using System;
    using System.Threading;
    //Example showing use of Join()
    public class ThreadTest4 {
     public class MyJob {
      public static int counter = 0;
      public int waitfor=1;
      public int finalState = -1;
      //sleeps then fills in finalState to simulate work done
      public void runme() {
      Thread.Sleep(waitfor);
      finalState = waitfor;
      Console.WriteLine(Thread.CurrentThread.Name+" finished sleeping finalState: "+finalState);
      }
     }
     
        public static void Main(string[] args) {
     MyJob myJob = new MyJob();
     myJob.waitfor = 2000;
     Thread thread = new Thread(new ThreadStart(myJob.runme));
     thread.Name = "first";
            
     MyJob myJob2 = new MyJob();
     myJob2.waitfor = 4000;
     Thread thread2 = new Thread(new ThreadStart(myJob2.runme));
     thread2.Name = "second";
            
     thread.Start();
     thread2.Start();
     
     Console.WriteLine("After start.");
     Console.WriteLine("Before first join.");
     thread.Join();
     Console.WriteLine("After first join.");
     Console.WriteLine("Before second join.");
     thread2.Join();
     Console.WriteLine("After second join.");
     
     Console.WriteLine("myJob.finalState="+myJob.finalState);
     Console.WriteLine("myJob2.finalState="+myJob2.finalState);
        }
    }
    This produces
    After start.
    Before first join.
    first finished sleeping finalState: 2000
    After first join.
    Before second join.
    second finished sleeping finalState: 4000
    After second join.
    myJob.finalState=2000
    myJob2.finalState=4000
  7. Join() with timeout What if a process may never finish? The Join() method has an optional parameter specifying how many millisecs to wait. The Join will give up after that time and return a 'false'. The following example shows the main thread waiting 2 seconds for a job that will take 8 seconds. After waiting 2 seconds, it gets a 'false' value back implying it did not finish in 2 seconds. Lacking any mercy we waste the process and move on to wait for the second, which has already completed.
    using System;
    using System.Threading;
    //Example showing use of Join()
    public class ThreadTest6 {
     public class MyJob {
      public static int counter = 0;
      public int waitfor=1;
      public int finalState = -1;
      //sleeps then fills in finalState to simulate work done
      public void runme() {
      Thread.Sleep(waitfor);
      finalState = waitfor;
      Console.WriteLine(Thread.CurrentThread.Name+" finished sleeping finalState: "+finalState);
      }
     }
     
        public static void Main(string[] args) {
     MyJob myJob = new MyJob();
     myJob.waitfor = 8000;
     Thread thread = new Thread(new ThreadStart(myJob.runme));
     thread.Name = "first";
            
     MyJob myJob2 = new MyJob();
     myJob2.waitfor = 500;
     Thread thread2 = new Thread(new ThreadStart(myJob2.runme));
     thread2.Name = "second";
            
     thread.Start();
     thread2.Start();
     
     Console.WriteLine("After start.");
     Console.WriteLine("Before first join.");
     bool finished = thread.Join(2000);
     if(!finished) { thread.Abort(); }
     Console.WriteLine("finishedP:"+finished);
     
     Console.WriteLine("After first join.");
     Console.WriteLine("Before second join.");
     thread2.Join(2000);
     Console.WriteLine("After second join.");
     
     Console.WriteLine("myJob.finalState="+myJob.finalState);
     Console.WriteLine("myJob2.finalState="+myJob2.finalState);
        }
    }
    Which produces:
    After start.
    Before first join.
    second finished sleeping finalState: 500
    finishedP:False
    After first join.
    Before second join.
    After second join.
    myJob.finalState=-1
    myJob2.finalState=500

< Prev  1 24  Next > 

C Sharp By Examples 2

< Prev  13 4  Next >
LINQ, Language Integrated Query, is a great new feature of C# 3.0. This page gives a small overview of LINQ. Before we start with LINQ we have to understand some new features of C# 3.0 that were added so LINQ could work.
  1. New Features in C# 3.0
    1. Lambda Expressions Lambda expressions are a list of inputs, the "=>" symbol, and an expression body.
      x => x * 0.05
      We can make using delegates shorter by using a lambda expression:
      // CalculateTax is a delegate that takes a double and returns a double
      public delegate double CalculateTax(double x);
      static void Main(string[] args) {
          CalculateTax stateDelegate = x => x * 0.05;
          CalculateTax federalDelegate = x => { if (x > 1000.0) return x * 0.02; else return 0.0; };
          double amountOfPurchase = 12.99;
      
          Console.WriteLine("{0}", stateDelegate(amountOfPurchase));
          Console.WriteLine("{0}", federalDelegate(amountOfPurchase));
      
          Console.In.ReadLine();
      }
      When using more than one input variable, surround the input with parenthesis and separate with commas.
      using System;
      namespace PlayingAround {
          class Lambda {
              public delegate int Largest(int x, int y);
              public static Largest myLargest = (int x, int y) => { return x > y ? x : y; };
              private static void Main() {
                  Console.Out.WriteLine("myLargest(4,5) = " + myLargest(4,5)); //prints 5
                  Console.Out.Write("press return to exit.");
                  Console.In.ReadLine();
              }
          }
      }
      Although these examples are painfully contrived, the common use of lambdas are in LINQ being used as anonyous delegates.
    2. Passing a lambda function to a method with void return type If we want to pass a lambda function that has a void return type and a single argument we use the system "Action" delegate. What we'd really like to do is use something like "Func<string,void>", but "void" is not a valid type, so instead we must use the "Action" delegate.
      using System;
      namespace PlayingAround {
          class MyAction {
              public static void Main()
              {
                  Action<string> printMe = x => Console.Out.Write(x);
                  Action<string> printMeAllCaps = x => Console.Out.Write(x.ToUpper());
      
                  ExecuteThreeTimes(printMe, ".");
                  ExecuteThreeTimes(printMeAllCaps, "aBc");
                  //produces "...ABCABCABC"
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
      
              private static void ExecuteThreeTimes(Action<string> func, string s)
              {
                  func(s);
                  func(s);
                  func(s);
              }
          }
      }
    3. Using FuncFunctions are now a first class citizens in .Net. You can declare them with "Func". Func's take all their argument types and then their return type at the end as shown below:
      using System;
      namespace PlayingAround {
          class MyFunc {
              public static void Main()
              {
                  //this function takes a string and returns an int
                  Func<string, int> countMe = x => { return x.Length; };
      
                  LogMeInt(countMe, "lamb");
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
      
              private static int LogMeInt(Func<string, int> func, string s)
              {
                  int count = func(s);
                  Console.Out.WriteLine("count = " + count);//in real life we'd log the results to a db or something
                  return count;
              }
          }
      }
    4. Extension MethodsIn C#3.0 one of the very cool concepts is "Open Classes" where you can add methods to existing classes. In C# parlance this is an extension method. Below is an example of adding a new method to our old friend "string".
      using System;
      namespace PlayingAround {
          public static class MyStringExtensionClass {
              //wraps an xml tag around a string
      
              public static string Wrap(this string s, string tag) {
                  return "<" + tag + ">" + s + "</" + tag + ">";
              }
          }
          class TestMe {
              static void Main(string[] args) {
                  Console.WriteLine("Warning".Wrap("h1"));   // <h1>Warning</h1>
      
                  Console.In.ReadLine();
              }
          }
      }
    5. Automatic PropertiesIn the old days before c# 3.0 you had to manually create the hidden variable behind fields:
      using System;
      using System.Collections.Generic;
      
      public class Book {
              private string _author;
              private string _title;
              public string Author {
                  get{return _author;}
                  set{_author = value;}
              }
              public string Title {
                  get{return _title;}
                  set{_title = value;}
              }
          public static void Main()
          {
              Book myBook = new Book();
              myBook.Title = "Gates of Fire";
              myBook.Author = "Stephen Pressfield";
              Console.In.ReadLine();
          }
      }
      
      With Automatic Properties, the compiler will generate a private field for you. You can change this later if you need to do something more elegant than just get the private field's value.
      using System;
      using System.Collections.Generic;
      
      public class Book {
          public string Author { get; set; }
          public string Title { get; set; }
      
          public static void Main()
          {
              Book myBook = new Book();
              myBook.Title = "Gates of Fire";
              myBook.Author = "Stephen Pressfield";
              Console.WriteLine(myBook.Title);
              Console.In.ReadLine();
          }
      }
    6. Local Variable Type InferenceThe compiler can infer the type of a variable from the expression on the right side. These are useful in LINQ expressions when the types can be overwhelming to enter, trust me. The type can be something like a function that takes a function with two ints and a float, and another function that takes a string and returns a function that takes two ints and a function that...
      It is important to remember that this is not a type-less variable, the complier just infers and checks it at compile time.
      var i = 6;  //trivial example, not really used in practice with ints
      Console.Out.WriteLine("i=" + i);
    7. Object Initialization in C# 3.0Objects can now be initialized in a more concise manner as shown below:
      ...
      public class House {
          public double price;
          public int stories;
          public string exterior;
      }
      class TestMe {
          static void Main(string[] args) {
              //old style
              House myOldHouse = new House();
              myOldHouse.price = 200000.00;
              myOldHouse.stories = 1;
              myOldHouse.exterior = "wood";
              //new style
              House myNewHouse = new House { price = 250000.00, stories = 2, exterior = "brick" };
              Console.In.ReadLine();
          }
      }
    8. Anonymous TypesWe can create anonymous types. The compiler will give our creation a hidden name.
      var animal = new  { IsMammal = true , Name = "lion" };
      Console.Out.WriteLine("Name="  + animal.Name);
      Console.Out.WriteLine("is mammal? "  + animal.IsMammal);
    9. Collection InitializersInstead of the klunky:
      ArrayList ab = new ArrayList();
      ab.Add("a");
      ab.Add("b");
      Using the collection initializer we can write
      ArrayList ab = new ArrayList {"a", "b"};
    10. AggregationAggregators are extension methods that act on IEnumerable<T>
      int[]  ints = { 1, 3, 5, 7 };
      Console.WriteLine(ints.Sum());  // 16 
      
      Console.WriteLine(ints.Min());  // 1 
      Console.WriteLine(ints.Max());  // 7 
      
      Console.WriteLine(ints.Average());  // 4 
    11. Expression TreesThis is a new feature in C# 3.0, which is not used by a typical developer, but are used by creators of LINQ-enabled storage devices.
    12. Partial FunctionsPartial functions allow class designers to put in hooks for future use. If the functions are never given substance, the compiler ignores them.
      using System;
      namespace PlayingAround {
          public partial class MyTest {
              partial void myPreHook();//never given substance, ignored by compiler
              public MyTest()
              {
                  myPreHook();
                  Console.Out.WriteLine("Creating MyTest.");
              }
              public static void Main() {
                  MyTest myTest = new MyTest();
      
                  Console.Out.Write("press return to exit.");
                  Console.In.ReadLine();
              }
          }
      }
      Adding a definition for myPreHook() will cause the compiler to generate the code and it will be executed.
      public partial class MyTest
          {
              partial void myPreHook()
              {
                  Console.Out.WriteLine("myPreHook.");
              }
          }
  2. LINQ - Language Integrated QueryLINQ is designed to work with any storage medium, e.g., SQL, XML, DataSets, or objects.
    LINQ has two syntaxes: query expression which is kinda SQL-like or standard dot notation which is standard c# . I prefer the dot notation since it really shows what is happening and it works with all query operators.
    Make sure you have a reference to "System.data.Linq.dll" in your solution.
    Below is an example using some of the LINQ features for in-memory objects. LINQ enables VStudio to give intelliSense to some queries. For in-memory LINQ, it's all about using the Standard Query Operators. These are extension methods on the IEnumerable<T> class, methods like "Where()","Select()","Sum()" and "Average()".
    1. Example using Standard Query Operators This shows the use of the Where(), OrderBy(), Count(), Sum(), Min(), Select(), and ForEach() methods.
      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      namespace PlayingAround {
          internal class Photo {
              public Photo(string photographer, string subject, int year, double cost) {
                  this.photographer = photographer;
                  this.subject = subject;
                  this.year = year;
                  this.cost = cost;
              }
      
              public string photographer { get; set; }
      
              public string subject { get; set; }
              public int year { get; set; }
              public double cost { get; set; }
      
              public override string ToString() {
                  return photographer + ", " + subject + ", " + year + ", " + cost;
              }
          }
      
          internal class PhotoLab {
              private static void Main(string[] args) {
                  List<Photo> list = new List<Photo>
                                         {
                                             new Photo("Frank", "Cats", 2002, 1.10),
                                             new Photo("Lee", "Dogs and Cats", 2003, 2.05),
                                             new Photo("Sarah", "Stingrays", 2007, 23.00),
                                             new Photo("Jon", "Meerkats", 2005, 16.75)
                                         };
                  //simple where clause
                  var oldPhotos = list.Where(p => p.year == 2003);
      
                  Console.Out.WriteLine("oldPhotos.Count() = {0}", oldPhotos.Count()); // 1
                  //Order Operators
                  //use OrderBy extension operator to sort
                  oldPhotos = list.OrderBy(p => p.year); //2002, 2003, 2005, 2007
                  foreach (var photo in oldPhotos) {
                      Console.Out.WriteLine("photo = {0}", photo);
                  }
                  oldPhotos = list.OrderByDescending(p => p.year); //2007, 2005, 2003, 2002
                  foreach (var photo in oldPhotos) {
                      Console.Out.WriteLine("photo = {0}", photo);
                  }
                  //Aggregate Operators
                  var number = list.Count(p => p.year > 2003);
                  //sums the length of all the photographer's names.  Did I mention this is a contrived example?
                  number = list.Sum(p => p.photographer.Length);
                  Console.Out.WriteLine("number = {0}", number); //16
                  //find shortest subject length
                  number = list.Min(p => p.subject.Length); 
                  Console.Out.WriteLine("number = {0}", number); //4
                  //using "Select" to create new anonymous classes
                  var photos = list.Where(p => p.year < 2005).Select(p => new {p.photographer, p.year});
                  foreach (var photo in photos) {
                      Console.Out.WriteLine("photo = {0}", photo); //photo = { photographer = Frank, year = 2002 }...
                  }
                  //write all photos to console
                  list.ForEach(p => Console.WriteLine(p));
                  //same as above but more concise, and a little spooky
                  list.ForEach(Console.WriteLine);
      
                  Console.In.ReadLine();
              }
          }
      }
    2. Create your own LINQ Query Operators Below is an example of extending the IEnumerable<T> class to include an operator that returns a List<T> of every other item.
      using System;
      using System.Collections.Generic;
      
      namespace PlayingAround {
          class EveryOtherExample {
              private static void Main() {
                  List<int> ints = new List<int>{0, 1, 2, 3, 4, 5, 6};
                  ints.ForEach(i => Console.Out.Write(i));
                  List<int> everyOther = ints.EveryOther(); //call our new Query Operator
                  everyOther.ForEach(i => Console.Out.Write(i));// writes 0246
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
          // let's create our own (non)Standard Query Operator
          /// <summary>
          /// returns every other item starting with the first item
          /// </summary>
          public static class MyEveryOtherExtensionMethod
          {
              public static List<T> EveryOther<T>(this IEnumerable<T> source)
              {
                  List<T> list = new List<T>();
                  bool shouldIAddIt = true;
                  foreach (var variable in source)
                  {
                      if(shouldIAddIt) {list.Add(variable);} //add every other one
                      shouldIAddIt = !shouldIAddIt;
                  }
                  return list;
              }
          }
      }
    3. Deferred QueriesMany of the standard query operators do not execute immediately, but wait until needed. In the example below "abc.Intersect(cdef)" is not executed until needed for printing. It is re-evaluted when needed again.
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class Deferred {
              private static void Main() {
      
                  List<string> abc = new List<string> { "a", "b", "c" };
                  List<string> cdef = new List<string> { "c","d","e","f"};
                  IEnumerable intersection = abc.Intersect(cdef); //deferred execution
                  cdef[3] = "a";
                  foreach (var letter in intersection) //now the IEnumerable intersection is done
                  {
                      Console.Out.WriteLine("letter = " + letter); //writes a,c 
                  }
                  cdef[2] = "b";
                  //Getting the Enumerator for "intersection" forces it to start to reconstruct the list again
                  foreach (var letter in intersection)
                  {
                      Console.Out.WriteLine("letter = " + letter); //writes a,b,c 
                  }
                  Console.Out.Write("press return to exit."); Console.In.ReadLine();
                  
              }
          }
      }
    4. Explicit InterfacesSometimes different interfaces have the same method signatures. To specify a specific interface, preface the method with the name of the interface followed by a ".". When calling the method, the object must be cast as that interface type.
      using System;
      namespace PlayingAround {
          class ExplicitInterface {
              interface IFlute {
                  void Play();
              }
              interface IGuitar {
                  void Play();
              }
              class Musician : IFlute, IGuitar {
                  void IFlute.Play() {
                      Console.WriteLine("Playing Flute");
                  }
                  void IGuitar.Play() {
                      Console.WriteLine("Playing Guitar");
                  }
              }
      
              public static void Main(string[] args) {
                  Console.WriteLine("hello");
                  Musician muscian = new Musician();
                  //muscian.Play();   error
                  //with Explicit Interfaces you must declare which interface is being called
                  ((IFlute)muscian).Play();
      
                  Console.ReadLine();
              }
          }
      }
    5. Creating an Xml document with Linq(namespace omitted for clarity)
      using System;
      using System.Xml.Linq;
      namespace PlayingAround {
          /// <summary>
          /// creates an xml document with nested elements
          /// </summary>
          class XmlCreate {
              private static void Main() {
                  XElement books = new XElement("books",
                      new XElement("book",
                         new XAttribute("title","Peopleware"),
                        new XElement("author","DeMarco and Lister")),
                       new XElement("book",
                         new XAttribute("title", "Agile and Iterative Development"),
                        new XElement("author", "Craig Larman")));
                  Console.Out.WriteLine("books.ToString() = \r\n" + books);
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
      Produces:
    6. Using LINQ to search xml filesWe use "var" as the type of "demarco_books" becasue the real type reported by "GetType()" is quite a mouthful, "demarco_books.GetType() = System.Linq.Enumerable+<WhereIterator>d__0`1[System.Xml.Linq.XElement]
      using System;
      using System.IO;
      using System.Linq;
      using System.Xml.Linq;
      
      namespace PlayingAround {
      
          class LinqXml {
              private static void Main() {
                  XElement books = XElement.Parse(File.ReadAllText(@"..\..\books.xml"));
      
                  IEnumerable<XElement> demarco_books = books.Elements("book").Where(book => book.Element("author").ToString().Contains("DeMarco"));
                  demarco_books.ToList().ForEach(b => Console.Out.WriteLine("DeMarco books:  " + b.Attribute("title")));
                  
                  Console.Out.Write("done.");
                  Console.In.ReadLine();
              }
          }
      }
      Given this xml file
      <books>
        <book title="Peopleware">
          <author>DeMarco and Lister</author>
        </book>
        <book title="Agile and Iterative Development">
          <author>Craig Larman</author>
        </book>
        <book title="Design Patterns">
          <author>Gamma, Helm, Johnson, Blissides</author>
        </book>
        <book title="Software Creativity 2.0">
          <author>Robert L Glass and Tom DeMarco</author>
        </book>
      </books>
      The program produces:
      DeMarco books:  title="Peopleware"
      DeMarco books:  title="Software Creativity 2.0"
      done.
    7. Using LINQ to sort objects
      using System;
      using System.Linq;
      
      namespace PlayingAround {
          class LinqArray {
              private static void Main() {
                  string[] presidents = {"Washington", "Madison", "Lincoln"};
                  //let's sort the array
                  var sorted = presidents.OrderBy(p => p);
                  sorted.ToList().ForEach(p => Console.Out.WriteLine(p));
      
                  Console.Out.Write("press return to exit.");
                  Console.In.ReadLine();
              }
          }
      }
    8. Using Legacy Collections C# offers a few ways to use older collections like ArrayList with LINQ. Cast() will try to cast all elements to the desired generic type. In the example below Cast() is successful in casting "12" to a string, so the number of elements is 5. OfType() will pluck out of the original Arraylist all the correct types, so its count is only 4. If we uncomment the line adding "new object()", which cannot be cast to a string, the Cast() method will throw an InvalidCastException, but the OfType() method will just ignore it.
      Some people will recommend using OfType() because it will not throw an exception when encountering an unexpected type of object. I usually prefer Cast() because I want to know up front during testing if any odd type has wandered into my collection. The only time to use OfType() is when you really expect to find mixed object types in your collection.
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq;
      
      namespace PlayingAround {
          class Legacy {
              private static void Main() {
                  ArrayList arrayList = new ArrayList();
                  arrayList.Add("up");
                  arrayList.Add("down");
                  arrayList.Add("charm");
                  arrayList.Add("strange");
                  arrayList.Add(12);
                  //arrayList.Add(new object());  //will cause exception in Cast()
      
                  IEnumerable<string> quarks = arrayList.Cast<string>().OrderByDescending(q => q);
                  Console.Out.WriteLine("Number of elements = " + quarks.Count()); //5
                  
                  quarks = arrayList.OfType<string>().OrderByDescending(q => q);
                  Console.Out.WriteLine("Number of elements = " + quarks.Count()); //4
      
                  Console.Out.Write("press return to exit.");
                  Console.In.ReadLine();
              }
          }
      }
    9. ProjectionProjection takes a series of one type of object and creates a series of another type.
      using System;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          public class Book
          {
               public string author;
               public string title;
               public string rating;
          }
          class Projection {
              private static void Main() {
                  List<Book> books = new List<Book>
                     {
                         new Book {author = "Demarco", title = "PeopleWare", rating = "Good"},
                         new Book {author="Tolkien", title="The Hobbit", rating="Super"},
                         new Book {author="Pressfield", title="Gates of Fire", rating="Super"}
                     };
                  //authorAndTitle has some machine-generated mangled type name
                  var authorAndTitle = books.Select(b => new {b.author, b.title}); //projection
                  authorAndTitle.ToList().ForEach(Console.WriteLine);
                  /* prints:
                      { author = Demarco, title = PeopleWare }
                      { author = Tolkien, title = The Hobbit }
                      { author = Pressfield, title = Gates of Fire } */
                  Console.Out.WriteLine("authorAndTitle type = " + authorAndTitle.GetType());
                  /* prints "authorAndTitle type = System.Linq.Enumerable+<SelectIterator>d__d`2[PlayingAround.Book,<>f__AnonymousType1`2[System.String,System.String]]" */
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    10. Partioning Functions Take(), TakeWhile(), Skip(), and SkipWhile()
      using System;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class TakeWhile {
              private static void Main() {
                  int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8};
                  //Take simply returns the first n elements
                  IEnumerable<int> three = numbers.Take(3);
                  three.ToList().ForEach(n => Console.Write(n)); //writes:  012
                  //TakeWhile returns elements until one of them is false and then stops
                  IEnumerable<int> odds = numbers.TakeWhile(n => n < 5);
                  odds.ToList().ForEach(n => Console.Write(n)); //writes: 01234
      
                  IEnumerable<int> skipFive = numbers.Skip(5); //skips first five
                  skipFive.ToList().ForEach(n => Console.Write(n)); //writes: 5678
      
                  Console.WriteLine();
                  IEnumerable<int> skipWhileLessThanFour = numbers.SkipWhile(n => n < 4);
                  skipWhileLessThanFour.ToList().ForEach(n => Console.Write(n)); //writes: 45678
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    11. Concatenationthe Concat() method joins lists
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class Concat {
              private static void Main() {
                  int[] little = { 0, 1, 2, 3, 4 };
                  int[] big = {  5, 6, 7, 8 };
                  IEnumerable<int> all = little.Concat(big);
                  all.ToList().ForEach(n => Console.Write(n)); //writes:  012345678
                  
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    12. SortingOrderBy(),ThenBy()
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class Order {
              public class Employee
              {
                  public string last; public string first; public double salary;
                  public Employee(string last, string first, double salary)
                  {
                      this.last = last;
                      this.first = first;
                      this.salary = salary;
                  }
                  override public string ToString() {return string.Format("{0}, {1}: ${2}", last, first, salary);}}
      
              public static void Main() {
                  Employee[] employees = {
                      new Employee("Jones", "Sara", 11000.00),
                      new Employee("Jones", "Brad", 10000.00),
                      new Employee("Aaron", "Mike", 10000.00),
                      new Employee("Xader", "Xena", 20000.00)
                      };
                  Print("No ordering", employees);
                  Print("Order by last", employees.OrderBy(n => n.last));
                  Print("Order by last, first",employees.OrderBy(n => n.last).ThenBy(n => n.first));
                  Print("order by salary", employees.OrderBy(n => n.salary));
                  Print("order by salary descending", employees.OrderByDescending(n => n.salary));
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
              static void Print(string title, IEnumerable<Employee> objects)
              {
                  Console.WriteLine(title+":");
                  objects.ToList().ForEach(n => Console.WriteLine(n));
              }
          }
      }
      Produces:
    13. Set OperatorsLINQ provides Union, Intersect, Distinct, and Except.
      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      namespace PlayingAround {
          class Sets {
              private static void Main() {
                  int[] little = {0, 1, 2, 3, 4, 5, 6};
                  int[] big = {5, 6, 7, 8, 9, 10};
      
                  IEnumerable<int> all = little.Union(big);
                  all.ToList().ForEach(n => Console.Write(n)); //writes 012345678910
                  Console.WriteLine();
                  IEnumerable<int> intersect = little.Intersect(big);
                  intersect.ToList().ForEach(n => Console.Write(n)); //writes 56
      
                  Console.WriteLine();
                  IEnumerable<int>  both = little.Concat(big);
                  both.ToList().ForEach(n => Console.Write(n)); //writes 01234565678910
      
                  Console.WriteLine();
                  IEnumerable<int> dist = both.Distinct();
                  dist.ToList().ForEach(n => Console.Write(n)); //writes 012345678910
      
                  Console.WriteLine();
                  //"Except()" returns all elements of the first sequence that do not exist in the second
                  IEnumerable<int> exceptional = little.Except(big);
                  exceptional.ToList().ForEach(n => Console.Write(n)); //writes 01234
      
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    14. Helper functionsRange, Reverse, Repeat, and Empty
      using System;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class Range {
              private static void Main() {
                  //note:  Range. Empty and Repeat are not extension methods, but static ones
                  IEnumerable<int> one2five = Enumerable.Range(1, 5);
                  one2five.ToList().ForEach(n => Console.Write(n)); //writes:  12345
      
                  IEnumerable<int> five2one = one2five.Reverse();
                  five2one.ToList().ForEach(n => Console.Write(n)); //writes:  54321
      
                  IEnumerable<int> fivethrees = Enumerable.Repeat(3,5);
                  fivethrees.ToList().ForEach(n => Console.Write(n)); //writes:  33333
      
                  //Empty creates an empty Enumerable of the specific type
                  IEnumerable<int> empty = Enumerable.Empty<int>();
                  fivethrees.ToList().ForEach(n => Console.Write(n)); //writes:
      
                  
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    15. NonDeferred Conversion MethodsToArray, ToList, ToDictionary, and ToLookup
      using System;
      using System.Collections.Generic;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
             public class BookItem
          {
               public string author;
               public string title;
               public string rating;
          }
          class NonDeferred {
              private static void Main() {
                  List<BookItem> books = new List<BookItem>
                     {
                         new BookItem {author = "Demarco", title = "PeopleWare", rating = "Good"},
                         new BookItem {author= "Tolkien", title= "The Hobbit", rating = "Super"},
                         new BookItem {author= "Pressfield", title = "Gates of Fire", rating = "Super"}
                     };
                  //convert to an array
                  BookItem[] bookItems = books.ToArray();
                  //convert to list
                  List<BookItem> bookList = books.ToList();
      
                  //now, finally something interesting, the dictionary, (one key to one object)
                  Dictionary<string, BookItem> dict = books.ToDictionary(b => b.author);
                  Console.Out.WriteLine(dict["Tolkien"].title); //writes:  The Hobbit
                  //now for something even more interesting, a Lookup (one key, many objects)
                  ILookup<string, BookItem> bookLookup = books.ToLookup(b => b.rating);
                  IEnumerable<BookItem> superBooks = bookLookup["Super"];
                  foreach (var book in superBooks)
                  {
                      Console.WriteLine("A super book is "+book.title); //writes:  The Hobbit, Gates of Fire
                  }
                  
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    16. Grabbing an item and searching for items
      using System;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class NonDeferred2 {
              private static void Main() {
                  string[] names = {"Cindy", "Bobby", "Jan", "Peter", "Marcia", "Greg"};
      
                  bool eq = names.SequenceEqual(names.Reverse().Reverse()); //returns true
                  // -- Finding an item
                  //First grabs the first item
                  Console.WriteLine(names.First()); //writes: "Cindy"
                  Console.WriteLine(names.First(p => p.StartsWith("J"))); //writes: "Jan"
                  Console.WriteLine(names.Last()); //writes: "Greg"
                  //selects the last item that matches a function
                  Console.WriteLine(names.Last(p => p.Length>4)); //writes: "Marcia"
                  Console.WriteLine(names.LastOrDefault(p => p.Length > 8)); //writes:
      
                  // -- Seaching for items
                  //Single returns the only element of a sequence, or throws an exception
                  try {
                      Console.WriteLine(names.Single()); //throws InvalidOperationException:
                  } catch(InvalidOperationException) {
                      Console.WriteLine("I was expecting only one element");
                  }
                  //with a predicate it returns the only one, or throws an exception
                  Console.WriteLine(names.Single(p=>p.StartsWith("B"))); //writes: "Bobby"
                  //ElementAt selects the element at that index (zero based)
                  Console.WriteLine(names.ElementAt(2)); //writes: "Jan"
                  //Any() returns true if the sequence has any elements
                  Console.WriteLine(names.Any()); //writes: "true"
                  //Any(p) return true if any element matches the predicate
                  Console.WriteLine(names.Any(p => p.Length>3)); //writes: "true"
                  //All(p) returns true only if all the elements match the condition
                  Console.WriteLine(names.All(p => p.Length > 4)); //writes: "false"
                  //Contains returns true if that object is in the sequence
                  Console.WriteLine(names.Contains("Carol")); //writes: "false"
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    17. Common math functions Count, Sum, Min, Max, and Average
      using System;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
          class Maths {
              private static void Main() {
      
                  int[] fibs = {0, 1, 1, 2, 3, 5, 8};
      
                  Console.WriteLine(fibs.Count()); //writes: 7
                  Console.WriteLine(fibs.Count(p => p < 3)); //writes: 4
      
                  Console.WriteLine(fibs.Sum()); //writes: 20
                  Console.WriteLine(fibs.Min()); //writes: 0
                  Console.WriteLine(fibs.Max()); //writes: 8
                  Console.WriteLine(fibs.Average()); //writes: 2.85714285714286
      
                  Console.Out.Write("press return to exit.");Console.In.ReadLine();
              }
          }
      }
    18. Aggregate, the "Reduce" function in LINQ
      using System;
      using System.Linq; //need this to get creamy goodness of IEnumerable<T> extension methods
      
      namespace PlayingAround {
      class Aggregate {
          private static void Main() {
              int[] numbers = {1, 2, 3, 4, 5, 6};
              //Aggregate performs a function on each of the elements and carries the result 
              //forward to the next element (Called a "Reduce" operation)
              int sumOfSquares = numbers.Aggregate(0, (sum,n) => n*n + sum);
              Console.Out.WriteLine("sumOfSquares = " + sumOfSquares); //writes: 91
       //concatenate all the strings together
              string allwords = 
                  words.Aggregate("", (temp, word) => temp + word);
              Console.Out.WriteLine("allwords = {0}", allwords); //writes:  onetwothree
              Console.ReadKey();
          }
        }
      }
       
       
      < Prev  13 4  Next >