Friday, May 27, 2011

Simpler TimeSpan construction

The TimeSpan structure in .NET is useful when you need to represent an interval of time. It has three different constructors that take varying degrees of days, hours, minutes, seconds and milliseconds to initialize the TimeSpan. This is great for its flexibility but all to often you just want a TimeSpan based on one value (like minutes or seconds) and all of the other values are zero. I've seen code like this to sleep a Thread for 10 seconds:
Thread.Sleep(new TimeSpan(0, 0, 0, 10, 0));

Thankfully there are a number of static convenience functions that take the single value and return a TimeSpan. They are all in form of FromX(double) where X maps to the same days, hours, minutes, seconds and milliseconds as above. So instead of the code above we can write:
Thread.Sleep(new TimeSpan.FromSeconds(10));

Nothing Earth shattering but just a little bit clearer for the next person who reads the code.

Thursday, May 26, 2011

Measuring time with Stopwatches

.NET 2.0 added the Stopwatch class that should definitely be in your tool belt for performance testing.
From MSDN:

The Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism. If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time. Otherwise, the Stopwatch class uses the system timer to measure elapsed time. Use the Frequency and IsHighResolution fields to determine the precision and resolution of the Stopwatch timing implementation.
Example:
Stopwatch stopWatch = Stopwatch.StartNew();
// Code to benchmark
stopWatch.Stop(); 
Console.WriteLine ("{0} ms", stopWatch.Elapsed.TotalMilliseconds);

Also note that the ElapsedMilliseconds property returns a rounded number to the nearest full millisecond, the Elapsed.TotalMilliseconds property is a float that can return execution times to the partial millisecond.

Update: Eric Lippert has a new series on benchmarking and highlights this approach in his second post.

Wednesday, May 25, 2011

Optional Parameters

.NET 4.0 added the often requested ability to specify a default value for a parameter making it optional for callers. The optional parameters have to be at the end of the parameter values and must be constants.
Generally they should be used where you would have created an overloaded method just to pass in a default value for one or two parameters. Don’t use them in place of good object initialization code or for every parameter a function takes.
For example the following overloaded methods:
/// <summary>
/// Return the contents of the text node associated with the passed element.
/// Return the empty string if there is no text node.
/// </summary>
public static string GetText(XmlElement element) {
     return GetText(element, string.Empty);
}


/// <summary>
/// Return the contents of the text node associated with the passed element.
/// Return the default value if there is no text node.
/// </summary>
public static string GetText(XmlElement element, string defaultValue) {

Can be simplified into one method by making the second parameter optional:
/// <summary>
/// Return the contents of the text node associated with the passed element.
/// Return the default value if there is no text node 
/// or empty string if not specified.
/// </summary>
public static string GetText(XmlElement element, string defaultValue = "") {

Note while you can use constants like int.MinValue and long.MaxValue, string.Empty is a field on the String class and cannot be specified. You have to use "" for empty strings.

Tuesday, May 24, 2011

IEnumerable(T) != IEnumerable

String.Join(String, IEnumerable(of T)) was added in .NET 4.0 as a new overloaded method that takes a strongly-typed enumeration and returns a separated string. This is great and something we had previously done in a wrapper function. However, one thing to be careful here is that passing in an ArrayList will not throw an exception (compile or runtime) but may not give you the results you are expecting.
For example the following code:
ArrayList array = new ArrayList() {1, 2, 3};
string joinedString = String.Join(",", array);
Console.Write(joinedString);

Will write out:
System.Collections.ArrayList

Not:
1, 2, 3