Pages

Tuesday, February 26, 2013

Slides + Code from LINQ Presentation



You can get the accompanying source from the presentation here (includes solution and project, just browse upward in the directory).

In the 10 examples you learn how to

1.  Create a query
2.  Create a query and have it produce a result
3.  Treat an expression predicate as a value
4.  Compile an expression tree to IL
5.  Use LINQ to objects
6.  Build a dynamic expression tree
7.  Compose Queries

Possible future additions : Discuss yield keyword, discuss LINQKit for composability

Code for main program embedded below as well



   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Threading.Tasks;
   6:  using System.Linq.Expressions;
   7:   
   8:  namespace PresentationV12
   9:  {
  10:      class Program
  11:      {
  12:          static void Main(string[] args)
  13:          {
  14:              #region Example 1 LINQ Query
  15:              using (var repository = new Database1Entities())
  16:              {
  17:                  var query = repository.Users.Where(user => user.UserId == 1);
  18:              }
  19:              #endregion
  20:   
  21:              #region Example 2 LINQ With Result
  22:   
  23:              using (var repository = new Database1Entities())
  24:              {
  25:                  var usr = repository.Users.Where(user => user.Username.EndsWith("Brian")).FirstOrDefault();
  26:              }
  27:              #endregion
  28:   
  29:              #region Example 3 Expression
  30:   
  31:              using (var repository = new Database1Entities())
  32:              {
  33:                  Expression<Func<User, bool>> expression = user => user.UserId != 5;
  34:   
  35:                  //Entity framework does similar parsing to the below and translates the expression to SQL
  36:                  ParameterExpression param = (ParameterExpression)expression.Parameters[0];
  37:                  BinaryExpression operation = (BinaryExpression)expression.Body;
  38:                  var left = operation.Left;
  39:                  var right = operation.Right;
  40:   
  41:                  var usr = repository.Users.Where(expression).FirstOrDefault();
  42:              }
  43:              #endregion
  44:   
  45:              #region Example 4 Not using Expressions - LINQ To objects
  46:              using (var repository = new Database1Entities())
  47:              {
  48:                  //Extension for IQueryable
  49:                  var usrs = repository.Users.Where(user => user.UserId != 5).ToList();
  50:   
  51:                  //Different extension method, IEnumerable.  
  52:                  var user2ndQuery = usrs.Where(user => user.UserId != 6);
  53:              }
  54:              #endregion
  55:   
  56:              #region Example 5 Compiling Expression Tree
  57:   
  58:              using (var repository = new Database1Entities())
  59:              {
  60:                  Expression<Func<User, bool>> expression = user => user.UserId != 5;
  61:   
  62:                  var usrs = repository.Users.ToList();
  63:   
  64:                  //Can't query objects with Expression<Func<User, bool>> expression
  65:                  //Error - var user2ndQuery = usrs.Where(expression);
  66:   
  67:                  //But you can reuse that expression like this to do that v
  68:                  var compiledExpression = expression.Compile();
  69:                  var user2ndQuery = usrs.Where(compiledExpression);
  70:              }
  71:              #endregion
  72:   
  73:              #region Example 6 Building a dynamic Expression tree 
  74:    
  75:              var param1 = Expression.Parameter(typeof(User), "user"); 
  76:              var prop = Expression.Property(param1, "UserId");
  77:              var Right = Expression.Constant(5);
  78:              BinaryExpression expr = Expression.MakeBinary(ExpressionType.NotEqual, prop, Right);
  79:   
  80:              var userExpression = Expression.Lambda<Func<User, bool>>(
  81:                  expr,
  82:                  param1
  83:                  ).Compile();
  84:   
  85:              using (var repository = new Database1Entities())
  86:              {
  87:                  var usr = repository.Users.Where(userExpression).ToList();
  88:              }
  89:   
  90:              #endregion
  91:   
  92:              #region My Number 1 Tip for writing good LINQ
  93:              //Compose your queries so you don't repeat yourself
  94:              //Lack of easy composability in SQL is the worst crux of writing SQL
  95:              //If you're copying and pasting a lot, you're doing it wrong
  96:              using (var repository = new Database1Entities())
  97:              {
  98:                  var userQuery = repository.Users
  99:                      .Where(UserNotTwo())
 100:                      .Where(UserNotBrian()).Where(NewMethod());
 101:   
 102:                  var usrList = userQuery.ToList(); //lazy evaluation "combines" both criteria 
 103:              }
 104:              #endregion
 105:   
 106:              #region SelectMany Flattening
 107:              //Flattens collections of collections
 108:              //Fairly common for a collection to contain collections with navigation properties in Entity Framework
 109:              //Necessary because there's no looping in a single LINQ expression--You'd have to bring the data down and loop yourself
 110:              //http://blog.falafel.com/Blogs/adam-anderson/2010/06/29/Flatten_Nested_Loops_with_LINQ_and_SelectMany
 111:   
 112:              using (var repository = new Database1Entities())
 113:              {
 114:                  var complexList = new List<List<string>>() { new List<string> { "test", "test2" }, new List<string> { "test3", "test4" } };
 115:                  var easyList = complexList.SelectMany(lst => lst);
 116:                  
 117:                  var superComplexList = new List<List<object>>() { new List<object> { "test", "test2", 25 }, new List<object> { "test3", "test4", new List<string>{ "test"} } };
 118:                  var kindOfEasyList = superComplexList.SelectMany(lst => lst);
 119:              }
 120:              #endregion
 121:          }
 122:   
 123:          private static Expression<Func<User, bool>> NewMethod()
 124:          {
 125:              return tt => tt.Email != "brian.rosamilia@gmail.com";
 126:          }
 127:   
 128:          #region Helper Functions
 129:          private static Expression<Func<User, bool>> UserNotBrian()
 130:          {
 131:              return usr => usr.FirstName != "brosamilia@example.com";
 132:          }
 133:   
 134:          private static Expression<Func<User, bool>> UserNotTwo()
 135:          {
 136:              return user => user.UserId != 2;
 137:          }
 138:          #endregion
 139:      }
 140:  }

Monday, February 25, 2013

6 Simple New(er) C#/.Net features you may have missed

So you're on an interview for a .NET job and you're feeling pretty good about yourself.  You've been using Visual Studio 2012 and .NET 4.5 for the last few months and your resume indicates the same; and then this question :

What are your favorite new features in C# 5.0 and .NET 4.5?

Uhh.. Well.  I....

It's actually a pretty difficult question this time around because it's not a major release and I would say that 3.0/3.5 was the last time I observed a radical change in the way we we write C#.

But could you even answer the question for .NET 4?    In this post I'm going to try to remind you of some of the features of C# 5.0/4.0 and .NET 4/4.5  that are both easy to remember and use.


BigInteger 


I thought we'd start simple.  In the Framework Class Library, there is a new DLL (System.Numerics) with  only two public types in it; one of them is the BigInteger struct.  BigInteger allows for arbitrarily long integers and could find use in scientific programming.

Tuple 


One of my favorite features in .NET 4 is the addition of the Tuple.  Tuples allow you to easily capture related values without having to go through the trouble of creating a new class.  It's a much more flexible concept than the KeyValuePair class because they can hold up to 8 values.

Tuple is a borrowed concept from F# that's been wedged into C# using the power of generics (and the copying and pasting of a class about 8 times).

Here's an example of the usage


   1:  public void Tuple()
   2:          {
   3:              var tup = new System.Tuple<int, string, DateTime>(1, "Brian", DateTime.Now);
   4:              Debug.Write(tup.Item1 + tup.Item2 + tup.Item3);
   5:          }


Here's the class I used above (The version that holds 3 generic values)


   1:  namespace System
   2:  {
   3:      [Serializable]
   4:      public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
   5:      {
   6:          public Tuple(T1 item1, T2 item2, T3 item3);
   7:   
   8:          public T1 Item1 { get; }
   9:       
  10:          public T2 Item2 { get; }
  11:       
  12:          public T3 Item3 { get; }
  13:   
  14:          public override bool Equals(object obj);
  15:          
  16:          public override int GetHashCode();
  17:        
  18:          public override string ToString();
  19:      }
  20:  }

Interesting to note that, yes there are 8 different versions of the class to support Tuples that hold up to 8 values.

Caller Information Attributes


Calling method arguments are a very useful feature implemented in the C# 5.0 compiler.  Now you can get information about how your method was called.  This is a huge improvement on having to look into the stack trace in order to achieve diagnostic level logging.  Here's an example of how it would work in a method that takes a string parameter.














Named and optional Arguments

Named and optional arguments are one of my favorite features because they allow API designers to have a LOT of calling options (as long as there are defaults) but not make your code verbose; I find any API taking advantage of this to be pure bliss.

Named Parameters allow you to specify  your parameters in any order and omit any parameters with defaults as long as everything without a default value is specified.

So for example, both of the following method calls are valid


   1:          public void NamedParameters()
   2:          {
   3:              OutPut(message: "Test");
   4:              OutPut(message: "Test", newLine:false);
   5:          }
   6:   
   7:          public void OutPut(bool newLine = true, string message = "TestMessage", bool AddAmperSand = true)
   8:          {
   9:              Debug.Write(message);
  10:              if (AddAmperSand) Debug.Write("&");
  11:              if (newLine) Debug.Write(Environment.NewLine);
  12:          }


Named parameters have another benefit; if you're working with a lot of code that has verbose calls that look like SendMessage(true, true,"messageData", false, 5)  and are completely unreadable because of the number of parameters.

you can refactor them into something like SendMessage(Repeat:true, Tolerance:true, Data:"MessageData", Alerts:false, RepeatSignal:5)

Of course this isn't a hard and fast rule, but more of a preference (I probably still lean toward the original.  There could be even more arguments though.).

ExpandoObject


An object you can dynamically add members to.  Lack of practical examples aside, there is a lot of possibilities because you can nest ExpandoObjects to create structured data (think XML-like/HTML-like).  You can think of ExpandoObjects as a Dictionary on steroids.  ExpandoObject is apart of the much bigger support for the Dynamic type introduced in C# 4.

   1:  public void ExpandoObject()
   2:          {
   3:              dynamic sampleObject = new System.Dynamic.ExpandoObject();
   4:              sampleObject.Test = "TestDynamic";
   5:              sampleObject.InvokeExpandoObject = new Action(() => Console.Write(sampleObject.Test));
   6:              sampleObject.InvokeExpandoObject.Invoke();
   7:          }

Parallel.ForEach


This concept is a small part of the much bigger task parallel library introduced in .NET 4.  The task parallel library is a collection of classes designed to make threading and parallel code easier to write.

If you have a list that needs to be processed, and you don't care about the order in which your items are processed, parallelizing your loop is likely a good idea. This is a really powerful concept because you aren't actually working with tasks at all and get the benefit of having your work parallelized.



Here's a simple example where we output a list in parallel.  You'll see the names don't come out in their original order.  Also, it should be noted that the overhead of the TPL is almost definitely not worth it in this scenario and is actually probably slower than a regular loop.

Conclusion / Download

You'll notice I left out Async/Await, Dynamic and Covariant/Contravariant generics and probably a bunch of other features.  The reason was to show you some of the SIMPLEST new features that will make your life easier.

It should be noted that the only feature I went over that's actually new in C# 5/ .NET 4.5 is calling method information--everything else is new as of .NET 4.

You can get the examples from this post here on bitBucket.  The total of all the examples is 70 lines!  Hopefully you've taken something away from this post.