Custom Iterators, Anmonymous/Generic Methods and Type Parameters

This article is a short summary/discussion of an excellent MSDN article titled “Custom Iterators” by Bill Wagner available here:

This initially made little or no sense to me. I am unfortunately used to pumping out pretty standard C# code – CRUD SQL plumbing and databinding – not really much mental excersise going on there. However this article is well worth reading as it uses a range of (not very new at all) C# 2.0 features, which will soon become much better known thanks to the advent of LAMBDA expressions and the like.

First of all, Generic Methods and Type Parameters:

A generic type is essentially a placeholder for a real type – and so a generic method is a method that accepts method specefic generic parameters – an example:

public void GenericMethods<T>(T param)

//And to use it:


//Or with type inference:



The important thins is that you can reuse this method with different types of data – and where this becomes really interesting is with delegates, because this allows you to setup blueprints (delegates) for methods that perform actions on generic types (and even easier with anonymous methods).

You can then pass these methods into methods that expect this delegate and construct some simple building blocks to reuse in your code.

C# Anonymous Methods

Anonymous Methods (C# Programming Guide)In versions of C# previous to 2.0, the only way to declare a delegate was to use named methods. C# 2.0 introduces anonymous methods. Creating anonymous methods is essentially a way to pass a code block as a delegate parameter.

An Example:

// Declare a delegate
// Declare a delegate delegate void Printer(string s); //MyOwnAnonymousMethod: delegate void TimeShouter(string a, int b); /// <summary> /// /// </summary> class TestClass { static void Main() { // Instatiate the delegate type using an anonymous method: Printer newP = delegate(string j) { System.Console.WriteLine(j); }; // The delegate instantiation using a named method "DoWork": Printer oldP = new Printer(TestClass.DoWork); // Results from the anonymous delegate call: newP("The delegate using the new anonymous method approach is called."); // Results from the old style delegate call: oldP("The delegate using the old named method approach is called."); TimeShouter ts1 = delegate(string name, int hour) { Console.WriteLine(String.Format("{0} shouts: \"What gives? it's {1} o'clock\".", name, hour.ToString())); }; TimeShouter ts2 = delegate(string name, int hour) { Console.WriteLine(String.Format("{0} also shouts: \"What the deuce? it's already {1} o'clock\".", name, hour.ToString())); }; //And reuse the anon method in another codeblock RoundTheClock(ts1, "John"); RoundTheClock(ts2, "Paul"); } // The method associated with the named delegate: static void DoWork(string k) { Console.WriteLine(k); } static void RoundTheClock(TimeShouter ts, string name) { for (int i = 1; i < 13; i++) { ts(name, i); } } }