SgDotNet
Singapore Professional .NET User Group -For Cool Developers

C# 2.0 Notable: Generics

[In my opinion, the most notable achievement of C# 2.0 is the extension of support for generic programming idiom, which is one of three main factors (the other two being availability of library and platform support) that otherwise drew me back to STL C++ from time to time, for the sake of its unlimited expressiveness!]

In C# 2.0, generics and generic collections are notable and very useful features to pay attention to: for your data structure needs, and data structure is the most important element for modeling! They are very similar to the philosophy of STL C++, in terms of predicate, functor etc.

Functor is short-term for function-object. Essentially, it introduces a parameterized behaviour that is extremly expressive and useful for manipulating collections, which are almost data structure is about. In terms of expressiveness, you can apply the parameterized behaviour to all elements of a collection with a single line (if not a few lines) of code. Making an analogy, think of Attributive Clauses in the grammar. 

Use (or rather, overuse) of generics is debatable at times. Some might argue the readability of resulted code using the argument like "keep it simple", but thinking of attributive clauses again, don't think they are everywhere and indispensable?  On the other hand, "everything should be made as simple as possible, but not simpler" (Enstein), so keeping it simple should never be a convenient excuse - less is more, but too less is none! Of course, this is defending use and not overuse of generics, against total dismiss of generics.


   Generic functors defined in C# 2.0 notable are :

public delegate void System.Action<T>(T t);
public delegate int System.Comparison<T>(T x, T y);
public delegate U System.Converter<T, U>(T from);
public delegate bool System.Predicate<T>(T t);

which represents the four immediate powerful feature of functor:

propagation: Action (let us do some thing from here for each item of the collections)
ranking relative order: Comparison (particularly within Sort operations)
transformation: Converter (let us convert to something desired inline for each item of the collections)
qualification: Predicate (whether this satisfy our criteria inline for each item of the collections, particularly within Find search operations)

Now if they are combined and made used inline within operations of collections such as:

pulic static U[] ConvertAll<T,U>(T[] array,Converter<T,U> converter);  // transformation  
public static bool Exists<T>(T[] array,Predicate<T> match); // qualification  
public static T Find<T>(T[] array,Predicate<T> match); // qualification  
public static T[] FindAll<T>(T[] array,Predicate<T> match); // qualification  
public static int FindIndex<T>(T[] array,Predicate<T> match); // qualification  
public static void ForEach<T>(T[] array,Action<T> action); // propagation  
public static void Sort<T>(T[] array,Comparison<T> comparison); // ranking

The possibilities becomes M*N and yet we only write M+N functions. 

The below gives some introductions:

Generic Collections I
http://blogs.msdn.com/jeremykuhne/archive/2005/07/22/441676.aspx
Generic Collections II
http://blogs.msdn.com/jeremykuhne/archive/2005/07/23/442148.aspx
Generic Collections III
http://blogs.msdn.com/jeremykuhne/archive/2005/07/24/442602.aspx
Generic Collections IV
http://blogs.msdn.com/jeremykuhne/archive/2005/07/24/442801.aspx

Another very good technical article, also on the enablers (anonymous methods and its use as inline delegate, ie creation of delegate objects from code bodies, with closure-converted by C# compiler)
http://msdn.microsoft.com/msdnmag/issues/06/00/C20

 

Among the contents of the article, not to be overlooked is the "iterator", which is a concept well defined and fully explored in STL C++. You can think of C#'s couterpart as a simpler, more straight-forward (of course, assisited by the compiler as any other innovative language features from assembly to c to c++ etc) way to implment IEnumerable, otherwise possible in C# 1.0 but could turn out to be tedious. The main enabler is the "yield" keyword.

One of the very interesting feature of such iterator is that it can mimic functional-style streams, which could be infinite.

static IEnumerable<int> Evens()
{ for (int i = 0; true; i += 2) { yield return i; } }
 


Posted Jul 05 2006, 01:45 PM by blackinkbottle
Filed under:
Copyright SgDotNet 2004-2008
Powered by Community Server (Commercial Edition), by Telligent Systems