Mark Needham

Thoughts on Software Development

Functional C#: Extracting a higher order function with generics

with 11 comments

While working on some code with Toni we realised that we'd managed to create two functions that were almost exactly the same except they made different service calls and returned collections of a different type.

The similar functions were like this:

private IEnumerable<Foo> GetFoos(Guid id)
{
    IEnumerable<Foo> foos = new List<Foo>();
    try
    {
        foos = fooService.GetFoosFor(id);
    }
    catch (Exception e)
    {
        // do some logging of the exception
    }
    return foos;
}
private IEnumerable<Bar> GetBars(Guid id)
{
    IEnumerable<Bar> bars = new List<Bar>();
    try
    {
        bars = barService.GetBarsFor(id);
    }
    catch (Exception e)
    {
        // do some logging of the exception
    }
    return bars;
}

We're defining the empty lists so that if the service throws an exception we can make use of an empty list further on in the code. A failure of the service in this context doesn't mean that the application should stop functioning.

My thinking here was that we should be able to pull out the service calls into a function but the annoying thing is that they return different types of collections so I initially thought that we'd be unable to remove the duplication.

Thinking about the problem later on I realised we could just define the return value of the service call in the function to use generics.

We therefore end up with this solution:

private IEnumerable<Bar> GetBars(Guid id)
{
	return GetValues(() => barService.GetBarsFor(id));
}
private IEnumerable<Foo> GetFoos(Guid id)
{
	return GetValues(() => fooService.GetFoosFor(id));
}
private IEnumerable<T> GetValues<T>(Func<IEnumerable<T>> getValues)
{
    IEnumerable<T> values = new List<T>();
    try
    {
        values = getValues();
    }
    catch (Exception e)
    {
        // do some logging of the exception
    }
    return values;
}

I think the code is still quite readable and it's relatively obvious what it's supposed to be doing.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • HackerNews
  • StumbleUpon
  • Twitter

Written by Mark Needham

February 8th, 2010 at 11:17 pm

Posted in .NET

Tagged with

11 Responses to 'Functional C#: Extracting a higher order function with generics'

Subscribe to comments with RSS or TrackBack to 'Functional C#: Extracting a higher order function with generics'.

  1. [...] This post was mentioned on Twitter by planettw, Agile Topic. Agile Topic said: Agile #Agile: Mark Needham: Functional C#: Extracting a higher order function with generics… http://bit.ly/9CDyNJ [...]

  2. Hi,

    I more and more end up with similiar code.
    Some times my code look like

    …. => {
    ….
    ….
    …. => {
    etc.
    }
    }

    BTW: why use the IEnumerable instead of plain T?
    In some cases the C# intference is not able to get it right but in most cases it works for me just fine.

    Heres one of my favs from my common DAL:

    public virtual IEnumerable<LazyReadonly> GetAll()
    { return GetEnumerable(
    env =>
    UseDataAdapter(
    env,
    adp =>
    GetAllRows(adp)
    .Select(r =>
    LazyReadonly.Create(
    GetKeyFromRow(r),
    () => RowToItem(r))
    )));
    }

    ;) (ok it messed up the spacing … thats something I didn't figure out for my code yet – how to space the lines)

    Carsten

    9 Feb 10 at 6:25 am

  3. [...] Functional C#: Extracting a higher order function with generics – Mark Needham continues his exploration of being more functional in your C# code illustrating with an example of refactoring a set of similar looking function calls which differed only by the service the call and the type they return. [...]

  4. Why do you always create a new list?

    IEnumerable values = new List();

    C# has a perfectly good coalescing operator (??) that you can use:

    return values ?? new List();

    This way the allocation only happens when you haven't been able to get the list (or if your getValues() function returns null)

    David Kemp

    9 Feb 10 at 9:32 am

  5. and you comments strips the <T>, damn!

    David Kemp

    9 Feb 10 at 9:34 am

  6. Mark,

    Would you ever add any type constraints to the generic function, i.e. "where T : ISomeInterface" or where T : class, new()" or do you not go that far because you're passing in the Func(..) that gets the values, so it can handle that?

    Matt Warren

    9 Feb 10 at 9:35 am

  7. If barService and fooService both implement IService which contains an IEnumerable GetFor(Guid id) then I think it'd be clearer to pass in an IService into GetValues rather than the Func<IEnumerable>.

    I find myself doing this stuff all the time now though. It's nice.

    Michael Chandler

    9 Feb 10 at 10:41 am

  8. Gah… they were IService(Of T) and IEnumerable(Of T) but you blog stripped them out.

    Michael Chandler

    9 Feb 10 at 10:42 am

  9. Hi Matt,
    just add constraints if you need them.

    Carsten

    9 Feb 10 at 12:26 pm

  10. I've started doing this all thetime when I have functionality that uses the same exception handling.

    nice to see other poeple doing this as well.

    Ollie Riches

    9 Feb 10 at 5:48 pm

  11. @David – yeah good point your solution would work better, didn't think of that.

    @Matt – haven't done anything with constraints as yet because it didn't seem necessary for what we were doing so far. I guess if it was a completely generic function that was used all over the code then constraints would make sense.

    @Michael – in fact in this case the two services don't implement the same interface otherwise your suggestion would certainly be the way to go.

    Mark Needham

    9 Feb 10 at 10:36 pm

Leave a Reply