Richer Languages Beyond the Sugar
Programming languages are not immutable. Especially when they're tightly coupled to a runtime environment such as the CLR, they progress as the underlying machinery is refined and enhanced. For example, the .NET Framework 2.0 supplied a C# compiler with additional features compared to the compiler for the .NET Framework 1.x. In Visual Studio 2008 and with .NET 3.5 onboard, you can use a significantly richer C# and Visual Basic .NET languages.
Both languages now incorporate features that enable functional programming and add specific keywords for Language Integrated Queries (LINQ).
Extension methods are a way to extend the otherwise hard-coded contract of a class by adding new methods programmatically without creating a derived or partial class. The idea behind extension methods is bringing the flexibility of duck-typing to a strongly-typed and compiled environment such as the CLR. In practice, you may use extension methods whenever you feel that a given class you're using lacks a helpful method. If you have no access to the source code of this class, in Visual Studio 2008 you define an extension. Extension methods can be defined for any class, including native classes of .NET. Listing One shows how to extend the System.String class with a few methods such as IsDate, IsInt32, and ToDate.
namespace Samples { public static class StringExtensions { public static bool IsInt32(this string content) { int number; bool result = Int32.TryParse(content, out number); return result; } public static bool IsDate(this string content) { DateTime date; bool result = DateTime.TryParse(content, out date); return result; } public static DateTime ToDate(this string content) { DateTime date; bool result = DateTime.TryParse(content, out date); if (result) return date; else return DateTime.MinValue; } public static int ToInt32(this string content) { int number; bool result = Int32.TryParse(content, out number); if (result) return number; else return Int32.MinValue; } } }
An extension method is defined as a static method on a static class. The binding between the method (say, IsInt32) and type (say, System.String) is established through the this keyword in the method's prototype:
public static bool IsInt32 (this string content)
The type that follows the this keyword is treated as the type to extend. Figure 3 shows IntelliSense in action on the extended System.String type.
The following code illustrates how you can use these new methods in your code:
void btnDate_Click(object sender, EventArgs e) { string content = textBox1.Text; if (content.IsDate()) { DateTime date = content.ToDate(); label2.Text = String.Format("Next day is {0}", date.AddDays(1).ToString("dd MMMM yyyy")); } else label2.Text = "Not a valid date."; }
Extension methods are checked at compile-time and can be applied also to any parent class or interface in .NET. (Extension methods could be used to obtain a feature that looks similar to mix-ins. Overall, a mix-in is a sort of interface with implemented methods. A class that implements a mix-in includesbut not inheritsall the members on the mix-in's interface. Currently, C# and Visual Basic .NET don't natively support mix-ins, even though instructing the compilers to produce the code for it didn't appear to be a huge effort. With extension methods, you can simulate mix-ins in the latest C# and Visual Basic .NET.)
The var keyword is another interesting new entry. Used to qualify a variable, it doesn't indicate a late-bound reference. Instead, it merely indicates that you don't know the type of the variable at the time of writing. However, the type won't be determined at runtime (late-binding), but the compiler infers the type from the expression assigned to the var variable. For this reason, an initial value assignment is required to avoid a compiler error. When var is used, a strongly typed reference is always generated.
The var keyword enables another cool C# featurethe anonymous type. This is an unnamed type that you define using the same object initializer syntax mentioned earlier:
var person = new { FirstName="Nancy", LastName="Davolio", Age=28 };
For the CLR, anonymous and named types are exactly the same entity. Anonymous types can be used in a variety of scenarios, but have been introduced primarily to support LINQ queries.
The same can be said for lambda expressions. Lambda expressions are used as a convenient way to create delegates, especially (but not uniquely) in LINQ. In .NET, a delegate is an object-oriented wrapper for a function pointer and points to an existing and named function in a class. In .NET 2.0, managed languages offered new, powerful constructanonymous methods. Basically, you have an explicit code snippet defined inline and used as an unnamed method of some class. Lambda expressions are a further refinement of the idea of an anonymous method, just less verbose and niftier.