14 January 2008

Compacting C# code using implicit properties, object initialization and lambda expressions

Not exactly hot science anymore - most could be distilled from Scott Guthrie's blog and numerous others, but this shows how you can use new C# 3.0 features to compact your code and make it more readable at the same time Suppose you have a simple person class sporting a first name, a last name and a birthdate. In the old days you would make something like this:
public class Person
{
    string _firstName;
    string FirstName
    {
        get
        {
            return _firstName;
        }
        set
        {
            _firstName = value;
        }
    }

    string _lastName;
    string LastName
    {
        get
        {
            return _lastName;
        }
        set
        {
            _lastName = value;
        }
    }

    DateTime _birthDate;
    DateTime BirthDate
    {
        get
        {
            return _birthDate;
        }
        set
        {
            _birthDate = value;
        }
    }
}
To create a list of these objects would be something like
List<Person> opList = new List<Person>
Person p1 = new Person();
p1.FirstName = "Joost";
p1.LastName = "van Schaik"
p1.BirthDate = new DateTime( 1969,06,03);
opList.Add( p1);
// etc.
To make things easier for you class user you could provide it with constructors, but as the numbers of properties grow, so does the number of (potential) constructors. To actually do something with the resulting list, you could do a foreach( OPerson p in opList) etc, or write something like this:
l.ForEach(delegate(Person p)
{
  Console.WriteLine(p.FirstName);
});
It works but I always thought this to be a bit of an awkward way of making predicates Implicit properties For a class as simple as the Person, you don't need to define 'backing variables anymore. These are inferred from code. Therefore, we can refactor the person class like this:
public class Person
{
    public Person()
    {
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}
That's rather compact, I'd say Object initalization The creation and initalization of a object can be written as follows:
Person p1 = new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)});
And while we are at it, the creation of a list of persons could be even simpler:
List<Person> l= new List<Person>
{
    new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)},
    new Person { FirstName = "John", LastName = "Doe", BirthDate = new DateTime(1970, 01, 01) },
    new Person { FirstName = "Michel", LastName = "van Schaik", BirthDate = new DateTime(1970, 12, 25) }
};
Lambda expressions And finally, picking out the first name myself and my family members would require only one line:
List<Person> vanSchaik = l.FindAll(p => p.LastName == "van Schaik");
And writing them out, too
vanSchaik.ForEach(p => Console.WriteLine(p.FirstName));
Conclusion The new features of C# can be used to make code more compact and better readable at the same time. Lambda expressions is certainly something you need to get used to reading, but for simple expressions they make life a heck of a lot easier. Complex expressions are hard to understand and read, though. Keep in mind that the next programmer may have a hard time reading your code, so don't use it just for the sake of it.