Adventures in .NET 3.5 Part 3
This is the 3rd part in a series. See Part1 and Part 2.
Inferring a Collection Type
In C# 3.5, the compiler can (typically) infer the type of a
collection. The member type doesn't need to be explicitly
specified.
var nums = new[] { 1,2,3 };
or
var states = new[] { "NSW", "WA", "QLD", "SA",
"TAS", "VIC" } ;
We could now apply the Concatenate and Print
extension methods from
Part 1, in order to create an array, and output it to the console
in a single line ...
new[] { 1,2,3,4,5 }.Concatenate().Print(); //
displays: 12345
Transforming the Collection
What I'd now like to do, is be able to easily transform the collection. For example, using the "states" array declared earlier, I'd like to be able to say something like...
var lowerStates = states.Transform( s => s.ToLower() );
Or, double each of those "nums" ...
var doubled = nums.Transform( n = > n *= 2 );
Out of the box I haven't been able to do that. Sure you could use the Array.ConvertAll() method, but that doesn't provide the neat syntax I'm after.
So what to do? The Each() extension method I created in the previous post won't work either, because it simply accepts an Action delegate that returns void. The framework Predicate delegate doesn't help either because it returns a bool.
3.5 introduces a general Func() delegate that we might use later, but for now what we really need is a delegate of T that returns T, so I'll create one.
public delegate T Transformation<T>(T obj);
Now that we have that, we can create an extension method that meets our needs ...
public static IEnumerable<T>
Transform<T>(this IEnumerable<T> items,
Transformation<T> transform)
{
foreach (var item in items)
{
yield return transform(item);
}
}
Let's convert those states to lowercase, and as
before apply the Concatenate() and Print() methods to output
lowercase states to the console
states.Transform( s => s.ToLower() )
.Concatenate(", ")
.Print("States: ");
// outputs "States: nsw, wa, qld, sa, tas, vic"
I haven't touched on LINQ yet, but it
introduces a new standard query syntax. We can use some of
the extension methods built in to the framework to support
it to further enhance our previous statement. Note the
framework Where() and OrderByDescending()
extension methods below. Any guesses as to the output?
states.Transform( s => s.ToLower() )
.Where( i => i.Contains("w") )
.OrderByDescending( i => i )
.Concatenate(", ")
.Print("States: ");
// outputs ?