James Michael Hare

...hare-brained ideas from the realm of software development...
posts - 166 , comments - 1483 , trackbacks - 0

My Links

News

Welcome to my blog! I'm a Sr. Software Development Engineer in the Seattle area, who has been performing C++/C#/Java development for over 20 years, but have definitely learned that there is always more to learn!

All thoughts and opinions expressed in my blog and my comments are my own and do not represent the thoughts of my employer.

Blogs I Read

Follow BlkRabbitCoder on Twitter

Tag Cloud

Article Categories

Archives

Post Categories

.NET

CSharp

Little Wonders

Little Wonders

vNext

C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

This week is my final entry in my Little Wonders series (posts one and two are here and here).  These are those little tips and tricks in .NET (and in particular C#) that may not seem like much, but can help make your code either more concise, maintainable, or performant.

Thanks again for all your comments and suggestions on this series, it has been a lot of fun to write, and though I feel I could go on forever with lots more tips and tricks, this will be the last Little Wonders post for a while.

1. Implicit Typing

First of all, let’s set the record straight for those confused: implicit typing is not dynamic typing.  Any identifier that is implicitly typed with the keyword var is still strongly typed.  The only difference is that the type is implied from the assignment expression.

Many think implicit typing is somehow lazy or inferior.  I must admit that when I first saw it I kind of felt the same way, but then after thinking about life in C++ with the STL iterators when you typed stuff like:

   1: for (list<int>::const_iterator it = myList.begin(); it != myList.end(); ++it)
   2: {
   3:     // ...
   4: }

I began to realize how much of a time-saver, and readability-saver, implicit typing is (those of you in C++ will be happy to know you now have implicit typing through the rebirth of the auto keyword).

For example, how many times do you have to type code like this:

   1: // pretty obvious
   2: ActiveOrdersDataAccessObject obj = new ActiveOrdersDataAccessObject();
   3:  
   4: // still obvious but even more typing
   5: Dictionary<string,List<Product>> productsByCategory = new Dictionary<string,List<Product>>();

Does explicitly typing obj or productsByCategory here really gain you anything?  Isn’t it obvious what the types are since we’re assigning them in the same statement?  It is so much cleaner just to say:

   1: // nicer!
   2: var obj = new ActiveOrdersDataAccessObject();
   3:  
   4: // Ah, so much nicer!
   5: var productsByCategory = new Dictionary<string,List<Product>>();

And let the var keyword do the work for you.  C# will examine the assignment expression and see what type it is, and then do the assignment.

Now obviously, there are times you want your variable to be a super-class or interface and those times explicit typing is what you’ll need, but don’t shy away from var because some think it’s lazy.  It can be abused, like any good tool, but it can also really improve your readability.

In fact, it really improves readability with generics and with LINQ expressions.  For example, compare these two:

   1: // implicit typing
   2: var results1 = from p in products where p.Value > 100 group p by p.Category;
   3:  
   4: // explicit typing
   5: IEnumerable<IGrouping<string, Product>> results2 = from p in products where p.Value > 100 group p by p.Category;

Whenever you start making heavy use of generics, collections, and especially LINQ expressions, you can rely on var to both make your code more readable, and to figure out what the type of the expression will be for you. 

2. LINQ Extension Methods

How many times have you written your own sort, find, grouping, or any other such standard algorithm?  Now how many hours have you spent writing unit tests for those methods?  And finally how many times have you been bitten by a trivial bug in one of those simple algorithms because of a typo?

With the LINQ extension methods, you have an arsenal of ready-made algorithms at your finger-tips which have already been tuned and unit-tested.  Really and truly, you should never have to write those standard algorithms again. 

Want to sort?  Use OrderBy().  Want to filter by a condition?  Use Where().  Want to select a subset of properties?  Use Select().  Want to group by a property?  Use GroupBy().  These are just a small taste of the many extension methods that were added to support LINQ and they are are fully tested and tuned!

For example, let’s say you have a List<Product> where Product, among other things, has a Value and a Category.  And let’s say you want to find a list of your high value products (> $100) by category.  Well, if you want to do it old-school you could write:

   1: var results = new Dictionary<string, List<Product>>();
   2:  
   3: foreach (var p in products)
   4: {
   5:     if (p.Value > 100)
   6:     {
   7:         List<Product> productsByGroup;
   8:         if (!results.TryGetValue(p.Category, out productsByGroup))
   9:         {
  10:             productsByGroup = new List<Product>();
  11:             results.Add(p.Category, productsByGroup);
  12:         }
  13:  
  14:         productsByGroup.Add(p);
  15:     }
  16: }

but that’s quite a mouthful of code, and to make matters worse if we do anything wrong it could be erroneous as well.  Why not just use the LINQ extension methods instead:

   1: var results = products
   2:     .Where(p => p.Value > 100)
   3:     .GroupBy(p => p.Category);

Or if you like, as a LINQ to objects expression:

   1: var results = from p in products where p.Value > 100 group p by p.Category;

The algorithms are already written for you and unit tested to boot!  Why rewrite code and risk the bugs?  Yes, you’ll have to learn lambda expressions or the LINQ query language if you aren’t used to them yet, but once you do a whole new world of powerful algorithms and expressions will be open to you!

3. Extension Methods

Depending on who you talk to extension methods are either the embodiment of evil, or really cool.  I tend to find them somewhere in between.  Are they as cool or as powerful as LINQ?  No, but it’s largely due to them that LINQ has a lot of its power. 

So why did Microsoft give us extension methods?  Why not just expand all the collections with various Select(), Where(), and other such LINQ methods?  Well, the answer is that not all collections have the same base classes and very few of them are implemented the same way.  In fact the one interface that seems to tie the most collections together is IEnumerable and as you know, you can’t add functionality to an interface directly.

So Microsoft added the ability to create a static method in a static class that behaves like it’s a member of the class that it is called on.  This has some interesting ramifications including that you can call an extension method off of a null reference (whether or not you should do this is hotly debated of course).

So let’s say you want to create an extension method that makes it easy to turn any object into an XML string.  We could write:

   1: public static class ObjectExtensions
   2: {
   3:     public static string ToXml(this object input, bool shouldPrettyPrint)
   4:     {
   5:         if (input == null) throw new ArgumentNullException("input");
   6:  
   7:         var xs = new XmlSerializer(input.GetType());
   8:         
   9:         using (var memoryStream = new MemoryStream())
  10:         using (var xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding()))
  11:         {
  12:             xs.Serialize(xmlTextWriter, input);
  13:             return Encoding.UTF8.GetString(memoryStream.ToArray());
  14:         }
  15:     }
  16: }

Note that the class we define the extension methods in must be a static class, and the first parameter of the extension method has the keyword this in front of its type.  This means that this static method will be invoke-able directly from any object of that type (in this case object, or anything).

Now, we can easily write:

   1: // can convert primatives to xml
   2: string intXml = 5.ToXml();
   3:  
   4: // can convert complex types to xml
   5: string objXml = employee.ToXml();
   6:  
   7: // can even call as static method if you choose:
   8: objXml = ObjectExtensions.ToXml(employee);

Note that this is just syntactical candy.  You are not really providing anything special here other than the fact that you can treat the extension method as if it is a member of the type it is “extending”.  As such, it is a very powerful tool in your toolbox for making code more readable, but be careful!  Overusing extension methods can make code less readable and may pollute your IntelliSense.

As general rules of thumb, I say prefer extension methods for types that you cannot extend (not yours or sealed) or for adding global functionality for interfaces (like IEnumerable).  But if the class is already under your control, prefer to add a real instance method instead.

4. System.IO.Path

The .NET System.IO.Path class has a plethora of static methods for dealing with files and paths that should make any manual manipulation on your side obsolete.

How many times have you tried to combine a path name and file name by hand and ended up botching it up because you expected (or didn’t expect) the path to have a trailing path separator (‘\’) character?  Well, there is the Path.Combine() static method that can take care of that:

   1: // combines a series of path name components into one path
   2: string fullPath = Path.Combine(workingDirectory, fileName);

Or what if you have a fully qualified path name to a file and you just want the file name, or just the path itself, or just the extension?  There are a plethora of Path static methods for giving you what you need!  No more need to do string searches and substrings when you can just use these:

   1: string fullPath = "c:\\Downloads\\output\\t0.html";
   2:  
   3: // gets "c:\"
   4: string pathPart = Path.GetPathRoot(fullPath);
   5:  
   6: // gets "t0.html"
   7: string filePart = Path.GetFileName(fullPath);
   8:  
   9: // gets ".html"
  10: string extPart = Path.GetExtension(fullPath);
  11:  
  12: // gets "c:\downloads\output"
  13: string dirPart = Path.GetDirectoryName(fullPath);

So before you go manually manipulating those filenames and paths, consider the Path class and its static methods.

5. Generic Delegates

If you’ve ever written or used a class that had events, or used one of the many of the LINQ extension methods, then chances are you’ve used either directly or indirectly used delegates.  Delegates are a powerful way to be able to create type that can be used to describe a method’s signature.  The actual method used and invoked, then, is specified later at runtime.  In C++ terms this is akin to using pointers-to-functions.

The great thing about delegates is they can make classes so much more reusable than inheritance can.  For example, let’s say you want to design a cache class and that class will contain a method, provided by the class’s user, that will determine if a cache item has expired and can be removed.  You could provide an abstract method that the user has to provide, but this means that the user would have to extend your class and override the method, which means a lot of extra work for providing that functionality.  In addition, this means you can’t mark your class as sealed to protect it from other non-related changes during inheritance.

This is where delegates become really powerful, you could provide a delegate that would specify a method type that can be called to check a cache item to see if it’s expired, and then when the user instantiates your cache, they can pass in or set the delegate to the method, anonymous delegate, or lambda they want called.  This way, no subclass is necessary and in fact you can seal your class to prevent unintentional changes.  This makes the class much more safe and reusable.

So what does this have to do with generic delegates?  Well, there are three basic “types” of delegates that appear over and over again, and rather than having to write these delegate types repeatedly, .NET has done you a big favor by making them generic so that they can be used repeatedly.  This also has the added benefit of making code that depends on delegates more readable, as these generic delegates are well understood in usage and intention:

  • Action<T> – A method that takes an argument of type T and returns void – generally used to perform an action on an item.
  • Predicate<T> – A method that takes an argument of type T and returns a bool – generally used to determine if an item meets a condition.
  • Func<TResult> – A method that returns a result of type TResult – generally used to generate values.

Note that these are the base forms of these generic delegates, and there are versions that take multiple parameters for each, the main thing that is constant is that Action returns void, Predicate returns bool, and Func returns a specified result.

So, to our cache example, say you wanted to write that cache that accepts a caching strategy, you would want a delegate that operates on an argument and returns a bool as to whether it has expired, that sounds like a Predicate:

   1: public sealed class CacheItem<T>
   2: {
   3:     public DateTime Created { get; set; }
   4:  
   5:     public DateTime LastAccess { get; set; }
   6:  
   7:     public T Value { get; set; }
   8: }
   9:  
  10: public sealed class Cache<T>
  11: {
  12:     private ConcurrentDictionary<string, CacheItem<T>> _cache;
  13:     private Predicate<CacheItem<T>> _expirationStrategy;
  14:  
  15:     public Cache(Predicate<CacheItem<T>> expirationStrategy)
  16:     {
  17:         // set the delegate
  18:         _expirationStrategy = expirationStrategy;
  19:     }
  20:  
  21:     // ...
  22:  
  23:     private void CheckForExpired()
  24:     {
  25:         foreach (var item in _cache)
  26:         {
  27:             // call the delegate
  28:             if (_expirationStrategy(item.Value))
  29:             {
  30:                 // remove the item...
  31:             }
  32:         }
  33:     }
  34: }

Then you can create the cache and use it without needing to sub-class. 

   1: var cache = new Cache<int>(item => DateTime.Now - item.LastAccess > TimeSpan.FromSeconds(30));

In fact, we can create as many caches we want with as many expiration strategies as we can think of and never need to subclass!  Know and use your generic delegates and it will really increase the re-usability of your classes.  In fact, any time when you are thinking of adding an abstract method and needing to provide functionality in a sub-class, if all you are doing is providing “hooks”, consider generic delegates instead.

Summary

Well, that’s the end of my “Little Wonders” series for now.  I really and sincerely hope you found something useful in at least one of these three posts.  If you did, feel free to spread it on!

I’ll leave you with 3 freebies that were too short to really devote to a section, but I so hated to leave them out!

  1. You can prefix string literals with @ so you don’t have to use escape sequences for paths, etc:
    • @”c:\downloads\data\files\d0.html” instead of “c:\\downloads\\data\\files\\d0.html”.
  2. You don’t need to create a new delegate for creating a new event handler, use the generic EventHandler:
    • public event EventHandler<MyEventArgs> OnClick;
  3. In a Windows Service Main method, you can query Environment.UserInteractive:
    • Tells you whether the application was started as a service or from command line/IDE.  You can query this bool to determine whether or not to start your service as normal, or whether to explicitly invoke OnStart() instead for debugging.  Smart application of this technique makes it easy to debug windows services in the IDE or from command line.

 

 

Print | posted on Thursday, September 9, 2010 6:06 PM | Filed Under [ My Blog C# Software .NET Fundamentals Little Wonders ]

Feedback

Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Another useful method in System.IO.Path class is GetFullPath method. If you use Combine method with a given directory path and a relative path, such as @“C:\Windows\System32\" and "..\..\Users\Administrator", you could get the absolute combined path "C:\Users\Administrator" by Path.GetFullPath(Path.Combine(@"C:\Windows\System32\", @"..\..\Users\Administrator"))
9/9/2010 8:02 PM | Pengzhi
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Really nice job!!!
I'll be looking forward for your next series.
9/9/2010 9:41 PM | Alejandro Miralles
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Cool series. Generic delegates rulezzz!
9/10/2010 12:09 AM | Nagor
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Nice series. I'm definitely stealing that ToXml() extension!
9/10/2010 12:39 AM | Lee D
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

What about VB versions? Or at least stating which of these also apply in vb as well would be very helpful..... And, if possible, code examples in vb as well would be nice but most vb devs know how to read c# code anyway... So what would add lots of value without taking much of ur time is stating which ofnthese also apply in vb and if necessary, how so etc... What do you think?
9/10/2010 1:19 AM | Erx
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Nice post. I already knew most of the methods but completely ignores the System.IO.Path namespaces. Excellent work.
9/10/2010 1:38 AM | Renzo
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

If you like System.IO.Path, then you should take a look at FluentPath (http://fluentpath.codeplex.com/) which upgrades it to the .Net 4.0 era.
9/10/2010 3:38 AM | Samuel Jack
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Wow great stuff man ... ToXml() is great but ToJSON() is better ;p
9/10/2010 8:12 AM | Phil Strong
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Thanks for all the comments! I really enjoyed writing the posts. Sorry about the ton of whitespace before the summary, I didn't catch that till just now. Fixed it.

@Phil Strong: agreed :-)
9/10/2010 8:48 AM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Great tips. Thanks a lot.
9/10/2010 11:29 PM | Raj
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

#2 would be nice if there was some place that could explain Lamda expressions so I could understand them. Really, it's horrible syntax like that that made me stop coding C++ and Java
9/13/2010 7:43 AM | LamdaLamdaLamda
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Yeah, I didn't want to get too deep into lambda syntax. Really all lambdas are are shot-hand syntax for anonymous delegates (yes, that's a bit of an oversimplification, but you get the point).

Eric White had an excellent tutorial or lambdas here:
http://blogs.msdn.com/b/ericwhite/archive/2006/10/03/lambda-expressions.aspx

I agree the syntax takes some getting used to, but once you do their power is awesome for writing short one-line methods that would ordinarily take up several lines of code as a traditional method.
9/13/2010 9:18 AM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Awesome series! Thank you!
9/13/2010 10:55 PM | Sameer
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Great series! Thanks for the reminder...I've certainly overlooked a few of these! I've found GetMethod from the System.Diagnostics.StackFrame class useful when logging errors to get the current method name:
new StackFrame().GetMethod().Name
9/14/2010 2:21 PM | Rod
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Hey James, first time commenting and I absolutely love your C# series. I always feel its the little details that separate good programmers from great ones. However, I'd like to say that with the LINQ Expressions in your #2 you should make a small mention about possible performance costs using LINQ. It's really a minor issue, really, since I do agree that LINQ expressions are much clearer but giving a complete picture of every tool will help us all. Other than that, absolutely love your work and look forward to future posts :)
9/14/2010 2:26 PM | John C.
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

C++0x supports the 'auto' keyword for type deduction purposes. Visual C++ 2010 supports it today. (http://msdn.microsoft.com/en-us/library/dd293667.aspx)
9/16/2010 3:21 PM | Dilip
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

@Dilip:

Yes, that's what I alluded to above. C++ now gives us the auto keyword which accomplishes the same thing as the 'var' keyword in C#.
9/16/2010 7:51 PM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Excellent Stuff...
That really helped a lot to me in reducing the code size and improved my coding style...

Thanks a Lot....

Enjoy Coding...
9/17/2010 2:16 AM | Aniket
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Thanks for the informative articles. I read all 3 and enjoyed them.

However, one thing which I just wanted to comment on. An overriding theme in your examples seems to be one of readability.

I have always found readability to be such a subjective metric. Every organization has slightly different standards and therefore a different take on what constitutes better readability. Therefore I would hesitate to ever make statements like "this is more readable".

Though I'm willing to admit that some things may be more universally readable than other things.

Specifically, the somewhat controversial "var" syntax.

More information (explicit declarations) are always better than less information. Especially in teams where not all the developers are of near-equal skill. Theres no room for misunderstanding, misinterpretation, or misuse of objects when using explicit declarations. Unless there is actually an application performance bonus to be gained, I believe shortcut syntax should generally be avoided.

Admittedly, in your first example of object instantiation:
ActiveOrdersDataAccessObject obj = new ActiveOrdersDataAccessObject();
vs.
var obj = new ActiveOrdersDataAccessObject();

One can easily get the type from the constructor call. However, some of us have been constructing objects in the same way for many years. In my mind, seeing the type first is as natural as reading the alphabet.

This example:
var results1 = from p in products where p.Value > 100 group p by p.Category;

Leaves everything up to the compiler to figure out, which I posit is actually harder to read for the developer precisely because the return type is not explicitly declared. It relies on strong familiarity with the language constructs.

Incidently, this also makes it harder to cross-skill people from c++ or java who all use the same syntax to instantiate objects.

Anyway, just my 2c. I enjoyed the examples nonetheless and even learned a few new things.
9/19/2010 12:46 PM | Greg
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

@Greg:

I partially agree. I find that the concept of readability mutates over time too. I used to think lambdas wholely unreadable, but now they are so much more concise than readng a large do-it-yourself for loop.

Is that to say you can't write really obfuscated lambda/LINQ code? Sure you can, readability is like anything, it's what you put in it.
9/23/2010 6:55 PM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Fantastic series. I hope to see more of these and it'd be nice if you could extend these to even design practices as well!
9/29/2010 12:40 PM | Ranganayaki
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

@Ranganayaki: Thanks and great idea!
9/30/2010 3:09 PM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

I'm sorry dude but you really needed more room and time and care when it came to describing the delegates. Tho I understand what your saying I can't go and start using them because the description was not enough for me. Maybe you should write a full blog on it and this time explain thing with the care to detail you normally do, assuming your reader knows nothing about the topic, what do you think?
10/23/2010 4:29 AM | Erx
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

@Erx:

Fair point I was trying to just decribe the generic delegates without getting too deep into delegates themselves for this post. I can try to do a more in depth description of them, though with more detail.
10/24/2010 9:43 AM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Good series of posts and its really helpful
11/25/2010 12:57 AM | Aravind
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Before using Path.Combine(), please read the manual carefully, especially the description of the 2nd parameter.
12/4/2010 8:12 AM | Martin Müller
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Thanks for a nice share you have given to us with such an large collection of information. Great work you have done by sharing them to all. simply superb
3/8/2011 1:25 AM | Buy Darvocet n100
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Great series, thanks.

First time I've really understood generic delegates properly (not to mention some of the other C# development topics earlier)!
3/15/2011 9:20 AM | Steve at Appetere
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Great Series. Hats off !
5/23/2011 6:24 AM | Reza
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Really fantastic series, thanks!
The bit on generic delegates has me interested in them again, after trying and failing for a long time to get my head around them...any chance of a more in-depth article?

p.s thank you so very much for not using Foo and Bar in your code samples. Whenever I see those my brain always just switches off. Don't know why but to me they actually make the samples harder to associate with :)
7/8/2011 11:42 AM | Steve
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

@Steve: Thanks! I have the generic delegates on my radar to dive deeper into either as a Fundamentals post or each as its own Little Wonder...
7/8/2011 4:00 PM | James Michael Hare
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

"First time I've really understood generic delegates properly (not to mention some of the other C# development topics earlier)! "

I feel the same!
8/26/2011 5:50 PM | Sample Hiphop
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

I already knew most of the methods, but completely ignores name spaces System.IO Path. Good job.
9/30/2011 8:59 AM | NCH Australia
Gravatar

# re: C#/.NET Five Final Little Wonders That Make Code Better (3 of 3)

Wow just woe for the series . What a collection of wonderful information. Really useful for quick reference. I am really 5 yrs late to see this article.
4/2/2015 1:23 PM | satya
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: