first glance at lambda functions in c# 3.0

When I first heard about lambda functions in c# 3.0, I were a bit sceptical, since the syntax is like nothing else I have seen.

I am still sceptical, but I can see places where they have their use, like in very simple selects from lists, simple string manipulations etc.

Like
	    string[] abs = new string[] { "Ab", "ab", "aB", "AB" };

            var abSelected = abs.Where(str => str == "ab");

            foreach (string p in abSelected)
            {
                Console.WriteLine(p);
            }

            var allAbs = abs.Where(str => str.ToLower() == "ab");
            foreach (string p in allAbs)
            {
                Console.WriteLine(p);
            }
Which shows an array of strings, where we first select those that matches "ab", lowercase, and then writes each one found out. Then it selects the same again, but ignores the case, and more or less selects everything.

Or a simple string manipulation:

	    var allCAPS = abs.Select(cap => cap.ToUpper());
            Console.WriteLine("ab all upper case\r\n");
            foreach (string p in allCAPS)
            {
                Console.WriteLine(p);
            }
Which basically converts all the strings to uppercase. In this example pretty useless, but it could be other string manipulations done.

objects are more or less the same syntax. Consider the following simple classes:

 public enum Sex
 {
     Female,
     Male,
     YesPlease
 }

 public class Person
 {
     public string Name
     {
         get;
         set;
     }

     public int Age
     {
         get;
         set;
     }

     public Sex Sex
     {
         get;
         set;
     }

     
 }
And the following snippets of code:

 List<Person> people = new List<Person>();
 
 Person person = new Person();
 person.Name = "Bjørn Smith";
 person.Age = 34;
 person.Sex = Sex.Male;
 people.Add(person);

 person = new Person();
 person.Name = "Female beauty hungry for sex";
 person.Age = 35;
 person.Sex = Sex.YesPlease;
 people.Add(person);

 person = new Person();
 person.Name = "Female beauty";
 person.Age = 18;
 person.Sex = Sex.Female;

 people.Add(person);

 person = new Person();
 person.Name = "Female blonde";
 person.Age = 25;
 person.Sex = Sex.Female;

 people.Add(person);

 person = new Person();
 person.Name = "Female brunette";
 person.Age = 38;
 person.Sex = Sex.Female;

 people.Add(person);
First a simple setup, to get some data to work with. I know the dataset is sparse, but it should be enough to show some ways of using lambda.

And then some simple queries to the list:

 Console.WriteLine("Female of all ages");
 var females = people.Where(a => a.Sex == Sex.Female || a.Sex == Sex.YesPlease);
 foreach (Person sexpartner in females)
 {
     Console.WriteLine(string.Format("{0}, {1} years", sexpartner.Name, sexpartner.Age));
 }

 Console.WriteLine("Order by age ascending"); females = people.Where(a => a.Sex == Sex.Female || a.Sex == Sex.YesPlease).OrderBy(a => a.Age); foreach (Person sexpartner in females) { Console.WriteLine(string.Format("{0}, {1} years", sexpartner.Name, sexpartner.Age)); } //For those really hungry we only want objects with name and sex var hungry = people.Where(a => a.Sex == Sex.YesPlease).Select(hu => new { hu.Name, hu.Age }); Console.WriteLine("Hungry only"); foreach (var femalehungry in hungry) { Console.WriteLine(string.Format("{0}, {1} years", femalehungry.Name, femalehungry.Age)); }

First query is just selecing all Person objects that have Sex as Female or YesPlease.

Please note the "strange" syntax of creating the "query" object by doing a: a => a.Sex ==  Sex.Female, which is exately the same as an anonymous delegate like delegate(string a) {return a.Sex == Sex.Female;}. I tend to like the last anonymous delegate more, since in my eyes its obvious what it does, but I'm sure that in time, I will embrace lambda functions where they make sense.

Second query is basically the same as the first one, but with the twist that we are ordering the list by Age ascending, just by doing a .OrderBy(a => a.Age), thats quite nifty I think, and if you compare to anonymous delegates, you would have had to do something like the following to have the same result:

 List<Person> femalePeople = people.FindAll(delegate(Person p)
 {
     return p.Sex == Sex.Female;
 }).Sort(delegate(Person ps1, Person ps2)
 {
     return ps1.Age.CompareTo(ps2.Age);
 });
So when you compare the two blocks of code, I see the benefit of lambda functions, but I still think they clutter the code, anonymous delegates easier to understand, but then again, it might just need some getting used to :)


The last select to the people list is basically the same, but we only select those that have YesPlease as Sex, and we create a new class on the fly with only two Properties, Name and Sex. Thats less usefull if you ask me, since you cannot return an object to the caller of a method, and get the type safety etc. But naturally you can manipulate the newly created objects, and you get intellisense and all the works, thats quite nice :)

This was my first glance at lambda functions, and it might be useful, I still need to see the definitive proof of their usefullness, in particular the feature to create anonymous types on the fly, but I am open to enlightenment :)