in

ASP.NET Weblogs

This Blog

Syndication

Christian Nagel's OneNotes

.NET Training, Consulting, Coaching - C#, Web Services, Enterprise Services, ASP.NET, Whidbey, Longhorn and More!

Generic Methods

Following my blog about Generic Delegates and Anonymous Methods, here is more:

Generics and anonymous methods can make code a lot more flexible.

Following I show different ways to accumulate the balance of Account objects. The Account class is a simple class that has a Balance property to access the balance of the class.

1. Summarizing the balance of Account objects in a collection can be done with the Accumulate method:

public static decimal Accumulate(IEnumerable e)
{
   decimal sum = 0;
   foreach (Account a in e)
   {
      sum += a.Balance;
   }
   return sum;
}

Invoking the method, the Account collection is passed:

decimal amount = Algorithm.Accumulate(accounts);

2. Making this method generic that it is possible to use other than Account objects, a generic method Accumulate can be implemented. However, because the Balance property is accessed for the accumulation, all generic TAccount classes must offer this property as is defined with the constraint IAccount.  

public static decimal Accumulate<TAccount>(IEnumerable<TAccount> coll)
   where TAccount : IAccount
{
   decimal sum = 0;
   foreach (TAccount obj in coll)
   {
      sum += obj.Balance;
   }
   return sum;
}

Invoking the method is not different to before:

decimal amount = Algorithm.Accumulate(accounts);

3. The second version has the requirement that all objects that are accumulated implement the Balance property. This can be more flexible by defining a generic delegate that defines the action.

Now the Accumulate mehtod can do anything to any object of a collection. What is done to the objects is defined with the delegate Action<>(). This Action delegate defines two parameters and a return type.

public delegate TSum Action<TObj, TSum>(TObj obj, TSum sum);

public static TSum Accumulate<TObj, TSum>(
  
IEnumerable<TObj> coll, Action<TObj, TSum> action)
{
   TSum sum = default(TSum);

   foreach (TObj obj in coll)
   {
      sum = action(obj, sum);
   }
   return sum;
}

To do the same as before - adding all balances - the implementation of the Action can be defined as anonymous method calling the Accumulate method.

decimal amount = Algorithm.Accumulate<Account, decimal>(
   accounts,
   delegate(Account a, decimal sum)
   {
      return a.Balance + sum;
   });

This is really flexible as it is not only possible to use Account objects, but any object. Instead of accumulating some values anything else can be done, too.

Of course anonymous methods should only be used with very simple implementations that are not needed somewhere else. Instead of anonymous methods a normal method can be used, too.

Christian

Comments

 

David Brabant said:

Always funny when people are (re)discovering techniques that have been applied in Lisp for close to half of a century ;-).

There is an old saying, which goes like "Any sufficiently sophisticated program implements a buggy subset of a Lisp interpreter". According to my experience, this has *always* been verified. :-)

Thanks for the article, anyway.
March 6, 2005 10:56 AM
 

RGabo said:

foreach (Account a in e)
{
sum += e.Balance;
}

should be

foreach (Account a in e)
{
sum += a.Balance;
}

generics, actions, predicates, anonymous methods make us developers look good :)
RGabo
March 6, 2005 12:18 PM
 

Christian said:

Thanks, RGabo.
March 7, 2005 1:42 AM
 

Christian said:

David, I've never written programs with Lisp, but I've used this technique with C++ before.

You've an interesting collection about exotic .NET languages: A#, Objective CAML, Lua, Ruby, F#, JACL.NET, G#, Common Larceny, OCamIL, P#, Boo!, Python, Beta, Forth, Nemerle, Dot-Scheme, Standard ML, IronPython, SmallScript:
http://www.xhovemont.be/category/36.aspx
March 7, 2005 1:53 AM
 

TrackBack said:

March 9, 2005 10:06 PM
 

TrackBack said:

March 11, 2005 6:34 PM
 

TrackBack said:

March 14, 2005 10:28 PM
 

TrackBack said:

April 27, 2005 10:35 AM
 

TrackBack said:

I am currently preparing my developer track talks for the local Big&gt;Days 2005 road show and - oh what...
May 9, 2005 4:24 AM
 

.NET Generics for generic solutions « The corner for basic and sharp net frameworkers. said:

February 3, 2007 6:53 PM

Leave a Comment

(required)  
(optional)
(required)  
Add