Showing posts with label Lambda expressions. Show all posts
Showing posts with label Lambda expressions. Show all posts

28 February 2010

Injecting logic in the middle of an algorithm using “Func<T>” function parameters

Sometimes you run into a situation in which you have a very similar complex pieces of logic, that only differ somewhere deep inside. This happens especially when you are dealing with legacy code that requires all kinds of weird initializers. Consider the following example, which is similar to something I ran into deep down in a CSLA library:

private void DataPortal_Fetch(string a, string b, string c)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = 
OldStaticHelper.GetByThreeStrings( a, b, c); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; } private void DataPortal_Fetch(string a, int n) { var helper = new LoaderHelper(); helper.Init(); LegacyObjectCollection result = OldStaticHelper.GetByOtherKeys( a, n); IsReadOnly = false; result.ForEach(p => Add(SomeNewObject.Get(p, helper))); RaiseListChangedEvents = false; IsReadOnly = true; }

The idea clearly was to call some legacy code and transform this into a list of “SomeNewObject”. But the annoying thing about the legacy code was that all kinds of helpers needed to be initialized before OldStaticHelper could be called. And then the logic of transforming the data had been duplicated as well. There are a number of ways to refactor this, but because I was fooling around with functional programming concepts at the time, I tried the following, which almost worked:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(OldStaticHelper.GetByOtherKeys( a, n));
}

private void FetchData(Func<LegacyObjectCollection> loaderMethod)
{
  var helper = new LoaderHelper();
  helper.Init();
  LegacyObjectCollection result = loaderMethod();
  IsReadOnly = false;
  result.ForEach(p => Add(SomeNewObject.Get(p, helper)));
  RaiseListChangedEvents = false;
  IsReadOnly = true;
}

Although this compiled an ran, it did not work as expected. Upon calling “FetchData” the OldStaticHelper.GetBy… method was instantly executed, in stead of of when “result = loaderMethod()” was called. And I just stated that it would not work unless the “helper” code was initialized. Thus, I needed to use delegates:

private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(() => OldStaticHelper.GetByThreeStrings( a, b, c)); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(() => OldStaticHelper.GetByOtherKeys( a, n));
}
Or, for those not familiar with the lambda syntax:
private void DataPortal_Fetch(string a, string b, string c)
{
  FetchData(delegate { return OldStaticHelper.GetByThreeStrings( a, b, c)}); 
}

private void DataPortal_Fetch(string a, int n)
{
  FetchData(delegate { return OldStaticHelper.GetByOtherKeys( a, n)});
}
Using this technique you can 'inject' a piece of logic into a larger algorithm, eliminating the need to duplicate code or making all kinds of in-between data sets

19 January 2010

One ForEach to rule them all

I ran into this when I was investigating functional programming in C#. That’s been around for a while, but apart from using it for traversing or modifying collections or lists, I never actually created something that was making use of a function parameter.

Anyway, one of my most used constructs is the ForEach<T> method of List<T>. I always thought it to be quite annoying that it is only available for List<T>. Not for IList<T>, ICollection<T>, or whatever. Using my trademark solution pattern – the extension method ;-)
I tried the following:

using System;
using System.Collections.Generic;

namespace LocalJoost.Utilities
{
  public static class GenericExtensions
  {
    public static void ForEach<T>(this IEnumerable<T> t, Action<T> action)
    {
      foreach (var item in t)
      {
        action(item);
      }
    }
  }
}

And that turned out to be all. IList<T>, ICollection<T>, everything that implements IEnumerable<T> – now sports a ForEach method. It even works for arrays, so if you have something like this

string[] arr = {"Hello", "World", "how", "about", "this"};
arr.ForEach(Console.WriteLine);
It nicely prints out

Hello
World
how
about
this

I guess it's a start. Maybe it is of some use to someone, as I plod on ;-)

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.