Register Login

 

Welcome to the Coach Factor blog. Here you will find all of our ideas on software development. Subscribe at  http://blog.nventive.net.

# Friday, April 24, 2009

So far, we’ve seen useful tricks to extend basic collection types like IEnumerable<T> and ICollection<T> but more complex collections deserve attention too!

 

Let’s look at IDictionary<T>. Here’s some code I stumbled upon recently; it is a partial implementation of IDataErrorInfo:

 

public class Order : IDataErrorInfo

{

    private IDictionary<string, string> errors =

        new Dictionary<string, string>();

 

    private decimal amount;

 

    public decimal Amount

    {

        get { return amount; }

        set

        {

            amount = value;

 

            if (amount <= 0)

            {

                errors["Amount"] = "Amount has to be larger than 0";

            }

            else

            {

                errors.Remove("Amount");

            }

        }

    }

 

    #region IDataErrorInfo Members

 

    public string Error

    {

        get { return null; }

    }

 

    public string this[string columnName]

    {

        get

        {

            if (errors.ContainsKey(columnName))

            {

                return errors[columnName];

            }

            else

            {

                return null;

            }

        }

    }

 

    #endregion

}

 

The interesting part is:

if (errors.ContainsKey(columnName))

{

    return errors[columnName];

}

else

{

    return null;

}

 

What’s the intent of this code? Pretty obvious isn’t it? It checks whether the dictionary has a value for a given key, then returns the value. If the key isn’t found, it returns the default value. This is similar to how the Nullable<T> type works:

int? index = null;

 

int indexValue = index.GetValueOrDefault();

 

Here, for obvious reasons, indexValue’s value will equal 0. But what’s interesting is the GetValueOrDefault() method. It clearly expresses the intent as opposed to:

int indexValue = index == null ? 0 : index.Value;

 

The same thing could apply to dictionaries but hasn’t been provided as part of the Base Class Library:

public string this[string columnName]

{

    get { return errors.GetValueOrDefault(columnName); }

}

 

Here’s Umbrella’s implementation:

public static class DictionaryExtensions

{

    public static TValue GetValueOrDefault<TKey, TValue>(

        this IDictionary<TKey, TValue> dictionary,

        TKey key)

    {

        return GetValueOrDefault(dictionary, key, default(TValue));

    }

 

    public static TValue GetValueOrDefault<TKey, TValue>(

        this IDictionary<TKey, TValue> dictionary,

        TKey key,

        TValue defaultValue)

    {

        return GetValueOrDefault(dictionary, key, () => defaultValue);

    }

 

    public static TValue GetValueOrDefault<TKey, TValue>(

        this IDictionary<TKey, TValue> dictionary,

        TKey key,

        Func<TValue> defaultValueProvider)

    {

        TValue value;

 

        if (!dictionary.TryGetValue(key, out value))

        {

            value = defaultValueProvider();

        }

 

        return value;

    }

}

 

The first method is an overload that will return default(T) if a default value is required.

The second method takes the defaultValue as a parameter

The third method contains the actual implementation and relies on a delegate to obtain the value since the defaultValue could either take some time to process or cannot be known in advance.

Again, these extension methods are small helpers to reduce the friction of th BCL. They are not meant to completely change the programming paradigm. They aren’t intrusive either. They should increase predictability of the source code with a side effect of decreasing the total lines of code count.

() => “Francois”

Friday, April 24, 2009 7:23:50 AM (Eastern Standard Time, UTC-05:00)  #    Comments [1] -
.net - Extension Methods | Umbrella
Search
Archive
<April 2009>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
Statistics
Total Posts: 98
This Year: 28
This Month: 3
This Week: 0
Comments: 17
Sign In