C# 3.0 has certainly introduced some really cool features. I have used the Automatic Properties extensively as well as object and collection initializers. These are real time savers.
However, the most exciting feature (IMHO) are Extension Methods. My last post shows one example of how powerful extension methods can be. Here is another example (inspired by Scott Gu).
1: public static class Extensions
2: {
3: ///
4: /// Do not use this extension for large sets because it iterates through
5: /// the entire set (worse case). i.e. O(n).
6: ///
7: public static bool In<T>( this T test, params T[] set )
8: {
9: return set.Contains( test );
10: }
11: }
Usage (excerpt from RowCommand event handler):
1: if( e.CommandName.In( "Open", "Close" ) )
2: {
3: ...
4: }
Instead of:
1: if( e.CommandName == "Open" ||
2: e.CommandName == "Close" )
3: {
4: ...
5: }
Here is another example:
1: public delegate T CreateIfNullDelegate<T>();
2: public static T GetValue<T>( this System.Web.Caching.Cache cache, string key, CreateIfNullDelegate<T> createIfNullDelegate, bool updateCache )
3: {
4: object value = cache[key];
5: if( value == null && createIfNullDelegate != null )
6: {
7: value = createIfNullDelegate();
8: if( updateCache )
9: cache[key] = value;
10: }
11: return (T)value;
12: }
13: ...
14: myData = Cache.GetValue<MyType>( myKey, myCreateDelegate, true );
15: myOtherData = Cache.GetValue<MyOtherType>( myOtherKey, myOtherCreateDelegate, false );
Instead of:
1: object value = cache[myKey];
2: if( value == null )
3: {
4: value = myCreateDelegate(); cache[myKey] = value;
5: }
6: myData = (MyType)value;
7: object value = cache[myOtherKey];
8: if( value == null )
9: {
10: value = myOtherCreateDelegate();
11: }
12: myOtherData = (MyOtherType)value;
I've used this extension repeatedly. A nice side effect is that the extension is more testable than a code-behind page.