Steve Michelotti

C#, ASP.NET, and other stuff

  Home  |   Contact  |   Syndication    |   Login
  51 Posts | 1 Stories | 155 Comments | 52 Trackbacks

News



Tag Cloud


Archives

Post Categories

Image Galleries

Articles

Blogs

Often when a new language features come out (in this case anonymous method) we often see syntax examples like this:

delegate void SomeDelegate();
public void InvokeMethod()
{
  SomeDelegate del = delegate()
      {
       MessageBox.Show("Hello");
      };
  del
();  
}

and we say, great but when is code like THAT ever going to be useful to me?  In that trivial example, of course that's not very useful.  But when you consider the power anonymous methods gives you both to pass in parameters and also make use of local objects then tons of possibilities are opened up for making code more concise and efficient.  Consider a case where you're using a DataReader to read multiple result sets.  Your code might look something like this:

public Person GetPerson(int personID)
{
 //(Perform data access code here to create DataReader)
 Person person = new Person();
 
 if (dr.Read())
 {
  person = personMapper.BuildItem(dr);
 }
 
 dr.NextResult();
 if (dr.Read())
 {
  person.Address = addressMapper.BuildItem(dr);
 }
 
 dr.NextResult();
 if (dr.Read())
 {
  person.EmploymentInfo = employmentMapper.BuildItem(dr);
 }
}

This code is now littered with IF statements and dr.NextResult() method calls.  To make this more concise, you could create a simple method that passes in a delegate that you can use anonymously:

public static void ReadNextResult(NullableDataReader dr, Execute execute)
{
 dr.NextResult();
 if (dr.Read())
 {
  execute();
 }
}

Then the consuming code can simply look like this:

public Person GetPerson(int personID)
{
 //(Perform data access code here to create DataReader)
 Person person = new Person();
 
 DataUtil.ReadNextResult(dr, delegate()
  { person = personMapper.BuildItem(dr); });

 DataUtil.ReadNextResult(dr, delegate()
  { person.Address = addressMapper.BuildItem(dr); });

 DataUtil.ReadNextResult(dr, delegate()
  { person.EmploymentInfo = employmentMapper.BuildItem(dr); });  
}

Notice that because of the use of anonymous methods, not only can we pass in the DataReader to the method but also we can use local objects (e.g., the “mapper” objects) inside the anonymous methods.  Internally the C# compiler creates private nested classes containing the delegates we want to execute that have member variables that are assigned the “local object” references which is why it's possible to pull this off in-line rather than having to create a completely separate method.

posted on Tuesday, March 21, 2006 8:51 AM

Feedback

# re: Real world example of C# Anonymous Methods 3/24/2006 12:33 PM Brian
It seems you could simplify this even more by creating an enumerable method and including the person object in each call.

e.g.:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging;
using System.Data.Common;

namespace TestLib
{

class Person : IEnumerable<Delegate>
{
public string Address;
public string EmploymentInfo;

public Person() { }

public Person GetPerson(int personID)
{
//(Perform data access code here to create DataReader)

Database D = DatabaseFactory.CreateDatabase();
DbCommand cmd = D.GetStoredProcCommand("GetPersonByID");
IDataReader dr = D.ExecuteReader(cmd);

Person person = new Person();

foreach (BuildItem bi in this.GetEnumerator()) { if (dr.Read()) { bi(person, dr); } } //does it all!
}

public delegate void BuildItem(Person p, IDataReader IDR);

public IEnumerator<Delegate> GetEnumerator()
{
yield return new BuildItem(personMapper.BuildItem);
yield return new BuildItem(addressMapper.BuildItem);
yield return new BuildItem(employmentMapper.BuildItem);
}
}

class personMapper
{
public personMapper() { }
public static void BuildItem(Person person, IDataReader IDR) { Person p = new Person(); }
}

class employmentMapper
{
public employmentMapper() {}
public static void BuildItem(Person p, IDataReader IDR) { p.EmploymentInfo = "Employment Info"; }
}

class addressMapper
{
public addressMapper() { }
public static void BuildItem(Person p, IDataReader IDR) { p.Address = "Address Info"; }
}
}





# re: Real world example of C# Anonymous Methods 3/27/2006 4:54 PM Steve
That is a cool example using iterators. However, I'm not sure I'd consider that more "simplified". :)

Essentially, you still have the 3 lines to call the various mapper BuildItem() methods but they take the form of a yield return with a foreach required. Plus, it necessitates that the various mapper objects are member variables whereas in the original solution you have the flexibility to use mapper objects that have either method level or class level scope (although in your code you changed the BuildItem() methods to be static). But regardless I still think the iterator implementation is a cool example of showing the flexibility that the new language features in C# 2.0 give you!

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: 
Please add 8 and 4 and type the answer here: