[UPDATE: Greg Young had a similar post on this subject that I somehow missed]
Ok, VS 2008 is out. You're on MSDN and you're patiently awaiting for the download to complete or you're already installing it.
Please stop for a second and read this blog post before you embark upon your C# 3.5 coding frenzy. Please consider the ramifications of C# Extension Methods. If you're not familiar with what C# Extension Methods are, please read Scott Guthrie's post on them, as it has all the details on the 'how'.
C# Extension Methods open up a lot of possibilities for a humble static-typed language like C# and many of these possibilities are just plain wrong, abusive, and harmful. Any language feature allows for writing poor code, but Extension Methods seem to pose an unusually high risk of abuse over existing and even other new-to-3.5 features. I'd like to start the discussion NOW before everyone goes hog wild on them and starts writing checks that maintenance programmers can't cash. I propose the following guidelines for using Extension Methods:
DON'T: Change State
Don't use extension methods to set properties on the 'this' instance, call state-changing methods, modify any fields, etc. Extension methods should be self-contained, utilitarian, necessarily short/concise, and obvious as to their purpose, function, and effect. To summarize: They should not produce unexpected, non-obvious results.
DON'T: Call External Services, Web Services, Database, or other unrelated code
Using extension methods for things like data access is a huge code smell and an abuse of the intention of extension methods. You can easily bewilder, confuse, and misdirect a maintenance programmer doing things like loading an entity from your ORM via a string (i.e. 'User u = "John Doe".LoadUserFromUserName()). Just because you can, and it might seem nifty/cool, doesn't mean it's the best thing. Keep the data access and other concerns like that out of your extension methods.
DO: Treat them like static, utility functions
We all have functions lying around, crammed into some global "LostAndFound"-type class which is the island of misfit functionality that doesn't seem to fit anywhere else in the OO world. Some of these functions are ripe candidates for Extension Methods -- things like handling DBNull vs decimal types, having a few Guid/String operations that are missing from the System.Guid class, etc.
DO: Limit the use of the 'new' operator
If you're having to 'new' up a bunch of classes in your Extension Method, this may be a clue/smell that something is wrong. One or a few 'new' operators is OK in specific situations (i.e. creating a Regex, for example), but if you have more than one or a few, perhaps it's time to move all this traffic-copping into some other, more meaningful and expressive class that handles whatever problem it is you're trying to solve with a bunch of 'new' operators.
DO: Assume maximum longevity, minimum change-ability
Due to their static nature, Extension Methods are going to be very difficult to maintain (think about a very well-known, highly used interface object in a popular framework package and then having to make a breaking change to it and all the people that would be affected). Design your Extension Methods for longevity. Plan on them never being able to have their signature changed and design with this in mind. This will (hopefully) force you to keep them short and sweet and, therefore, not likely to suffer a lot of changes or defects.
DO: Arrange your namespaces for maximum coexistence and flexibility of use
If you release your extensions to the public, plan on the fact that one of your terribly clever extensions (for example, string.IsValidEmailAddress()) will be implemented in another public extensions framework released some other time and that your user may wish to use the OTHER IsValidEmailAddress implementation, but still be able to use all your other extensions.
One way of doing this is to carefully plan out the Namespaces in which your extension classes will exist. Scott Bellware has a good post talking about this and he suggests putting them in a namespace that suggests what their concern is (for example, Time/Date stuff around Int32 -- stuff like 3.DaysAgo() -- would go into the namespace MyApp.Extensions.Int32Time.
This way, if I were your customer and I had another framework that implemented DaysAgo(this int32 days) in a better way, I could just not use your 'Int32Time' namespace, but still happily use the rest of your stuff.