August 31, 2008

StartsWithAnyOf extension method

Here comes another great string extension for improved readability. You all know how to check if a string starts with another string (yep, it's the StartsWith method I'm talking about).

But what if you wan't to check if a string starts with any of a series of strings? Well, you'd have to do something like this.

string name = "Mr. Markus Olsson"
var l = new List<string> { "Dr", "Mr", "Ms" };
bool found;
foreach(string s in l) {
    if(name.StartsWith(l)) {
        found = true;
        break;
    }
}

Or, you could use lambdas for a much more elegant solution

string name = "Mr. Markus Olsson"
var l = new List<string> { "Dr", "Mr", "Ms" };
bool found = l.Exists(prefix => name.StartsWith(prefix));

That's pretty cool, right? The .Exists method on the list object takes a Predicate as a parameter and executes that predicate with each element as it's first argument until it finds a match. Coolio indeed but we can do better readability wise.

Enter StartsWithAnyOf extension methods

/// <summary>
/// Checks to see if the string starts with any of the supplied strings
/// </summary>
/// <param name="s">The string to check for a start value</param>
/// <param name="strings">One or more strings</param>
/// <returns>True the strings starts with any of the supplied strings, false otherwise</returns>
public static bool StartsWithAnyOf(this string s, params string[] strings)
{
    if (s == null)
        throw new ArgumentNullException("s");

    if (strings == null)
        throw new ArgumentNullException("strings");

    if (strings.Length == 0)
        throw new ArgumentOutOfRangeException("strings", "You must supply one or more strings");

    return Array.Exists(strings, (prefix => s.StartsWith(prefix)); 
}

/// <summary>
/// Checks to see if the string starts with any of the supplied strings
/// </summary>
/// <param name="s">The string to check for a start value</param>
/// <param name="strings">One or more strings</param>
/// <returns>True the strings starts with any of the supplied strings, false otherwise</returns>
public static bool StartsWithAnyOf(this string s, List<string> strings)
{
    if (s == null)
        throw new ArgumentNullException("s");

    if (strings == null)
        throw new ArgumentNullException("strings");

    if (strings.Count == 0)
        throw new ArgumentOutOfRangeException("strings", "You must supply one or more strings");

    return strings.Exists(x => s.StartsWith(x));
}

This allows us to rewrite our code to

string name = "Mr. Markus Olsson"
bool found = name.StartsWithAnyOf("Dr.", "Mr.", "Ms.");

Readability in a nutshell. Variations of these extension methods includes an override that takes a StringComparison in order to allow for case insensitive lookup. The EndsWithAnyOf method is of course also a must.

Update: as mattias pointed out there's a bit of code duplication here but that's intentional, read why
Update 2: I changed my mind again after discussing it with mattias and for the sake of readability and code-duplication I've decided to wrap the first method into a call of the second.
Update 3: James Curran pointed out that the Array class have an Exist method and that's of course what you want for the string array. Thanks James!

Licensing information

kick it on DotNetKicks.com

August 30, 2008

Collection.IsNullOrEmpty

Ah, string.IsNullOrEmpty. It was love at first sight when I found that simple yet extremely useful method. It's quite often you want check if a string is null or empty. Instead of checking if the string is null and then checking if it is of zero length (or god forbid checking if it equals string.Empty) you can call this this method and it does it for you. Not only does it save you from unnecessary keystrokes, it also increases readability.

string s = null;
if(!string.IsNullOrEmpty(s))
    PerformWork(s);
instead of
string s = null;
if(s != null && s.Length > 0)
    PerformWork(s);

Well, you probably get my point, it's awesome. But I found that I still write if-statements checking for nullity and length of lists, hashsets and other collections. I can't quite figure out why the BCL team didn't include a corresponding method for collections (or perhaps they did? Enlighten me plix!). Don't despair though, uncle Markus is here to help.

using System.Collections;

namespace freakcode.Utils
{
   public static class Collection
   {
       /// <summary>
       /// Checks if the supplied collection is null or empty
       /// </summary>
       /// <param name="il">The collection</param>
       /// <returns>True if the collection is null or empty, false otherwise</returns>
       public static bool IsNullOrEmpty(ICollection ic)
       {
           return (ic == null || ic.Count == 0);
       }

   }
}

It's so simple it's almost embarrassing to post but it sure increases readability and it's a really great method to integrate and enforce in you own repository of utility methods.

var employees = new List<string>() {"Bob", "Alice", "Tom" };
if(Collection.IsNullOrEmpty(employees))
    FireTheirAsses(employees);

You could rename/copy this to List.IsNullOrEmpty if you think that produces cleaner and more readable code.

Licensing information

kick it on DotNetKicks.com

Code license information

Yup, we all have our problems with licenses. But I'm planning on throwing some code out to the reader(s) of this blog (hi mom!) and I thought that I'd make sense to make it clear from the beginning.

I have limited understanding of copyright law, especially US law but I suspect that most of the smaller code samples won't pass threshold of originality and thus isn't even copyrightable.

The code snippets that do pass the treshold is (unless otherwise noted) written by me and I will place them under the MIT-license and they can be used for whatever purpose you want, commercial or otherwise. Please give credit where credit is due though. Common sense applies. If you want to discuss specifics feel free to contact me.

In the case of blog posts concerning contributions to other projects where the project prohibits the use of MIT-license for contributions the supplied code will of course comply with the license of said project. Should I for example contribute to a project that's licensed under GPL my code will be licensed the same way.

If you like a particular snippet or code sample that I've posted, please link to it from your blog, your code where you integrated it or wherever. Help me gather some pagerank karma!

Inpossible word verification

That Chosen One pointed out how irritating it is to have to have to pass CAPTCHA every time you want to comment. I totally agree. I even had a hard time setting up this blog since the CAPTCHA was so hard to read. Therefore I've changed the settings so that word verification is no longer required for posting comments. Unfortunately this also means that you wont be able to post comments without having an OpenID or Google account.

August 29, 2008

Hello world

This intro is brought to you by the imaginary interviewer. For your viewing pleasure!

Oh, great, another developer, who are you?

I'm a developer from Sweden and currently I spend most of my time with .NET web and applications development. Exclusively C# for the .NET stuff. I'm employed by a small company (~12 employees) with big ambitions where I work on a product for which I was one of the founders. I'll share more on my work later on.

I've been an active developer for more years than I can remember and I have a broad background. I started with QBasic at age eleven or twelve continuing onto pascal and then back to VB. After that I jumped ship and became an avid linux supporter/developer/evangelist which resulted in quite a lot of bash scripting at first continuing onto C but that was not my cup of tea. I think PHP came next and I started a small consulting business along with some friends called Softdays development to do some web development (hey, everybody was doing it).

After building webshops for a while I found my first programming language love: python and I developed quite a lot of stuff in python before my work situation forced my into a radically new direction.

In the initial stages of planning for our new killer product at work I was introduced to my new colleague who was a real, all-the-way-to-the-bone Microsoft dude. Needless to say we fought like cats and dogs for about a year and there where a lot of hard discussions about how we where going to go about building this system of ours. We eventually settled (against my strongest recommendataion) on ASP.NET 2.0 (which was in early beta at the time), C# and SQL Server. I'm really glad we did because C# and .NET (especially with all the new cool features of .net 3.5) really rocks!

ENOUGH! We don't care! Why would we want another developer blog?

I don't think the world can get enough of developer blogs ;) Seriously though, I plan to blog for two reasons:

  1. To share the cool/time saving/bug killing code that I produce or find
  2. To keep myself up to date and to, hopefully, get some input from the community on what I'm thinking
That being said I don't have any special insight on how to avoid blogdeath. I've tried blogging before with, shall we say, limited success. But I think that's because I tried blogging about my general life and that's not interesting enough to write or read ;)

Okay, so what can we expect to read then?

I don't quite know yet. My general idea is that I'll be posting some cool code snippets to begin with and I'll definitely share my view on currently relevant questions and topics in the .net/c#/asp.net community.

I've lined up a couple of posts already that I'll be posting over the next couple of days (yup, they're already written) but other than that I think we'll just have to wait and see

Uh oh, I know where this is going, you wan't our help don't you?

Er, um... hmm. Well... I'd really like to try to get this blog going and to do that I'd really appreciate if you could spread the link to your developer friends and colleagues. I also gladly accept questions that you think would be interesting to blog about. Some pagerank karma wouldn't hurt either (link me plix!). If you'd like to write a guest-post that'd also be great.

Hey, wait a minute, aren't you swedish?

Thats correct, but this is not Sweden, this is the Internet and it only speaks english ;)

Yeah alright... how do I contact you then?

Oh, a new friend, yeay! Well, commenting is one way of course. Email is another, you'll find my email at www.freakcode.com/contact/