Saturday, December 01, 2007

For everyone that was at my DevTeach presentation thank you for showing up and listening to me. I had my adrenaline flowing and ended up finishing a little to early, if only I could code like that day to day!

If you have svn installed, you can download my presentation from the command line with the following command:

svn checkout http://stevenrockartspresentations.googlecode.com/svn/trunk/ devteachgenericspresentation

I still have to do one more check-in to add my reduce implementation and to clean up the code. I am also going to upload a zipped version of the code to the downloads section located here: http://code.google.com/p/stevenrockartspresentations/downloads/list

 

Here is a list of resources from the presentation:

- Combining Generics, Specifications and Functional Programming Part 1

- Combining Generics, Specifications and Functional Programming Part 2

- Combining Generics, Specifications and Functional Programming Part 3

- Combining Generics, Specifications and Functional Programming Part 4

- Follow up to Generics Presentation Feedback

- Reduce in C#

Saturday, December 01, 2007 5:12:27 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

I got a couple of emails with great feedback from my last couple of posts. I think I could probably turn this presentation into 2 different presentations but it is curing my blogging writers block so i'll post the responses here for everyone's benefit.

Shane was very quick to point out that the method signature in Customer is kind of misleading:

public bool IsAnActiveCustomer(ISpecification<Customer> activeCustomerSpecification)

We could actually pass any specification that implements the ISpecification interface into this function. We can refactor a little to make it a little more clear to someone consuming the Customer class:

public bool IsAnActiveCustomer()
{
    return this.Matches(new ActiveCustomerSpecification());
}
 
public bool Matches(ISpecification<Customer> specification)
{
    return specification.IsSatisfiedBy(this);
}

Using this approach we supply consumers of our class with a default for an active customer and allow them to specify their own specification for what constitutes an active customer.

One thing that I should have mentioned in my post is that Filter and Map are included in the List class in .NET 2.0. Filter == FindAll and Map==ConvertAll, here is the code from Reflector:

public List<T> FindAll(Predicate<T> match)
{
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    List<T> list = new List<T>();
    for (int i = 0; i < this._size; i++)
    {
        if (match(this._items[i]))
        {
           list.Add(this._items[i]);
        }
    }
    return list;
}
 
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
    if (converter == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
    }
    List<TOutput> list = new List<TOutput>(this._size);
    for (int i = 0; i < this._size; i++)
    {
        list._items[i] = converter(this._items[i]);
    }
    list._size = this._size;
    return list;
}
Saturday, December 01, 2007 3:39:40 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

At my DevTeach presentation I showed how you can do Map and Filter from Functional programming right now in C# 2.0. In mathematics Reduce is "the process of manipulating a series of equations or matrices into a desired 'simpler' format". In C# you can think of it as taking a list and reducing it down to one value. 

Here is my implementation of Reduce in C# 2.0:

[Test]
public void ShouldReduceListOfIntegersToTotal()
{
    IList<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Add(3);
    numbers.Add(4);
 
    RecordBook<int> recordBook = new RecordBook<int>(numbers);
 
    Assert.AreEqual(10, recordBook.Reduce<int, int>(numbers, Add));
}
 
[Test]
public void ShouldPrintIntegersAsOneString()
{
    IList<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Add(3);
    numbers.Add(4);
 
    RecordBook<int> recordBook = new RecordBook<int>(numbers);
 
    Assert.AreEqual("1234", recordBook.Reduce<int, string>(numbers, BuildStringFromIntegers));
}
 
private string BuildStringFromIntegers(int number, string test)
{
    return test + number;
}
 
private int Add(int number1, int number2)
{
    return number1 + number2;
}

and the implementation of the tests:

public delegate TResult Accumulator<TSource, TResult>(TSource x, TResult y);
 
public TResult Reduce<TSource, TResult>(IList<TSource> source, Accumulator<TSource, TResult> accumulator)
{
    TResult result = default(TResult);
 
    foreach (TSource item in source)
        result = accumulator(item, result);
 
    return result;
}

The first test calculates the sum of adding all the integers in the list together using the add function. The second test takes an integer and concatenates it to a string producing a string of all the integers in the list.

The Reduce function introduces the default keyword that you can leverage with generics. This will give you the default value for value types (0 for integers, 0.0 for decimals, null for string).

Saturday, December 01, 2007 1:21:02 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

Theme design by Jelle Druyts

Pick a theme: