C# 3.0 and .NET 2.0

Something I didn’t realize until just now: in Visual Studio 2008 you can target .NET 2.0 and still get C# 3.0 features:
 
– Anonymous types
– Automatic properties
– Lambda-expressions
– Object initializers
– Type inference with "var" keyword
 
I’ve known that .NET 3.5 targets the same CLR, but it’s still nice to learn that even though it says "Microsoft (R) Visual C# 2008 Compiler version 3.5.21022.8
for Microsoft (R) .NET Framework version 3.5" the target framework version can still be 2.0.
 
What you don’t get is extension methods and LINQ implementations (to object, to sql, to xml).
As it turns out extension methods support can be easily added and LINQ can have a custom implementation which would be the case with NHibernate anyways.
 
I’m sure there’s lot of useful stuff defined exclusively in .NET 3.5, like Func<> and such, still… sweet.
Advertisements
C# 3.0 and .NET 2.0

Chain delegates sample

In my post about "best code ever" I mentioned a way to chain conditions into a single Predicate<T>.
 
Let’s say you need to match a collection of items to number of specified "templates", following the rule:
 if all specified fields of any given template match the fields of an item – include the item in the result set
 
You could express it statically with a complicated bunch of if-statements or you could use functional programming.
This small program in C# 2.0 demonstrates how to do that:

class Item

{

    public int? Id;

    public string Notes;

    public string Text;

    public int? Number;

 

    public Item() { }

    public Item(int? id, int? number, string notes, string text)

    {

        Id = id;

        Number = number;

        Notes = notes;

        Text = text;

    }

}

 

class Program

{

    static Predicate<T> AndChain<T>(IEnumerable<Predicate<T>> unchainedPredicates)

    {

        Predicate<T> predicates = delegate(T item) { return true; };

        foreach (Predicate<T> predicate in unchainedPredicates)

        {

            // local copy insures the current predicate instead of the last one will make it into the anonymous delegate

            Predicate<T> p = predicate;

            Predicate<T> chain = predicates;

            predicates = delegate(T item) { return p( item ) && chain( item ); };

        }

        return predicates;

    }

 

    static Predicate<T> OrChain<T>(IEnumerable<Predicate<T>> unchainedPredicates)

    {

        Predicate<T> predicates = delegate(T item) { return false; };

        foreach (Predicate<T> predicate in unchainedPredicates)

        {

            // local copy insures the current predicate instead of the last one will make it into the anonymous delegate

            Predicate<T> p = predicate;

            Predicate<T> chain = predicates;

            predicates = delegate(T item) { return p( item ) || chain( item ); };

        }

        return predicates;

    }

 

    static void Main(string[] args)

    {

        List<Item> items = new List<Item>(

        new Item[]

        {

            new Item(1, 2, "note1","text1"),

            new Item(2, 1, "note2","text2"),

            new Item(3, 2, "note3",""),

            new Item(4, 2, "note4","text4"),

        } );

 

        Item[] templates = new Item[]

        {

            new Item( 1, null, null, null ),

            new Item( null, null, "note2", null ),

            new Item( null, 2, null, "text" )

        };

 

        foreach (Item item in items.FindAll( BuildPredicate( templates ) ))

        {

            Console.WriteLine( "{0}: {1},{2},{3}", item.Id, item.Number, item.Notes, item.Text );

        }

    }

 

    private static Predicate<Item> BuildPredicate(IEnumerable<Item> templates)

    {

        List<Predicate<Item>> predicates = new List<Predicate<Item>>();

        foreach (Item template in templates)

        {

            Item local = template;

            Predicate<Item>[] templatePredicates = new Predicate<Item>[]

            {

                delegate(Item item)

                { return !local.Id.HasValue || item.Id == local.Id; },

                delegate(Item item)

                { return string.IsNullOrEmpty(local.Notes) || item.Notes == local.Notes; },

                delegate(Item item)

                { return string.IsNullOrEmpty(local.Text) || (!string.IsNullOrEmpty(item.Text) && item.Text.Contains(local.Text)); },

                delegate(Item item)

                { return !local.Number.HasValue || item.Number == local.Number; },

            };

            predicates.Add( AndChain( templatePredicates ) );

        }

        return OrChain( predicates );

    }

}

 

The results of this program are:
1: 2,note1,text1
2: 1,note2,text2
4: 2,note4,text4
 
While this may look incomprehensible to an untrained eye, this code is actually very simple. There’s bunch of collections being declared and evaluated here and there. It is simple in term of static structure. At runtime it could become quite complex and may be difficult to debug using .NET IDE, but chances are you won’t have to.
 
There’s one problem that you might have in real life applying this – not all fields would be nullable. The good news is the concept of template would have some means to specify if particular field has a value that needs matching. In my case I was dealing with a web-service "boundry" class generated from WSDL that has "Specified" for all value-type fields. 
 
Also, instead of Predicate<Item> itself one could use another class that wraps the predicate and separates the applicability flag (i.e. local.Number.HasValue in the sample code) from the actual item evaluation. This allows for even finer-grained rules and flexibility in their application. That’s the approach I used, but I didn’t put it here for clarity.
 
Hopefully this illustrates that once your code "becomes data" you can manipulate it and it gets much easier to express complex concepts and change them every which way.
Chain delegates sample

Introducing functional programming to C#

I’ve been digging into functional programming and came a cross a need to have something like ‘self’ in my anonymous delegate.
The post here describes this and other tricks (available to trully functional languages out of the box) implemented in C# (unfortunately 3.0)
Introducing functional programming to C#

C# 3.0 – LINQ

I get LINQ now! wohoo!
 
All the syntax sugar added to C# 3.0 seems to be there for the benefit of LINQ. Makes it short and readble.
Can’t translate SQL into C#, right? Right? So, LINQ is the next best thing, especialy if lets you query any object/store.
 
And now to the example from C# spec that made me see the light:

The example

from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }

is translated into

from g in
      from c in customers
      group c by c.Country
select new { Country = g.Key, CustCount = g.Count() }

the final translation of which is

customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })

 
You can see the elemetal building blocks emerging: lambda expressions, extension methods, anonymous types, instance initializers.
 
Expression trees is what allows different backing for the same LINQ syntax:

Because a conversion exists to Func, a conversion also exists to Expression>.

Func f = x => x + 1;                   // Code

Expression> e = x => x + 1;       // Data

Following these assignments, the delegate f references a method that returns x + 1, and the expression tree e references a data structure that describes the expression x + 1.

Next on my list: finding out how are LINQ to XML, – to Objects, etc. work…

Found this nice description: http://community.bartdesmet.net/blogs/bart/archive/2007/04/06/the-iqueryable-tales-linq-to-ldap-part-1-key-concepts.aspx

 

C# 3.0 – LINQ

C# 3.0

 
Implicit typed local variables: are welcome.
 
Lambda-expressions: statement vs. expression body – can’t wait to get used to those.
 
Extension methods are freaking me out. Probably because it contradicts MS-own guidelines based on "the code is for humans to read".
 
Object initializers: Nice "short-cuts".

public class Point
{
      int x, y;

      public int X { get { return x; } set { x = value; } }
      public int Y { get { return y; } set { y = value; } }
}

An instance of Point can be created and initialized as follows:

var a = new Point { X = 0, Y = 1 }; 

public class Rectangle
{
      Point p1, p2;

      public Point P1 { get { return p1; } set { p1 = value; } }
      public Point P2 { get { return p2; } set { p2 = value; } }
}

An instance of Rectangle can be created and initialized as follows:

var r = new Rectangle {
      P1 = new Point { X = 0, Y = 1 },
      P2 = new Point { X = 2, Y = 3 }
};

which has the same effect as

var r = new Rectangle();
var __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
r.P1 = __p1;
var __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
r.P2 = __p2;

 or:

var r = new Rectangle {
      P1 = { X = 0, Y = 1 },
      P2 = { X = 2, Y = 3 }
};

which has the same effect as

var r = new Rectangle();
r.P1.X = 0;
r.P1.Y = 1;
r.P2.X = 2;
r.P2.Y = 3;

Collection initializers: sweet. 

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Anonymous types: useful. 

var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;

the assignment on the last line is permitted because p1 and p2 are of the same anonymous type.

Implicitly typed arrays: thanks!

var a = new[] { 1, 10, 100, 1000 };

 

 

 

C# 3.0