Joe White’s Blog

Life, .NET, and Cats


C# 3.0: Dictionary parameters (like in Ruby)

Eilon Lipton blogged about a way to get Ruby-like dictionary parameters in C# 3.0. (Link via Scott Guthrie‘s post on URL routing.)

Ruby lets you pass a dictionary as the last parameter(s) to a method. I won’t go into details, but the syntax looks like this:

get_html_link("Click me", "Key1" => "value1", "Key2" => "value2", "Key3" => "value3")

(Yes, the idiomatic usage would be to use :key1 instead of a string literal, but the strings are probably less confusing for the non-Ruby-adept.)

With Eilon’s code, you can get some very similar syntax in C#:

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

This code passes an anonymous type (that’s the new {...}), and then uses Reflection to read its properties. Reflection is not something you want to do in tight inner loops, but when readability is the main concern (as it is 95+% of the time), this technique is worth considering.

The place this is useful is when you’re really passing a dictionary of arbitrary values — when the function doesn’t know how many items to expect, or what they’ll be called. If, on the other hand, the function knows it’s expecting three properties called Key1, Key2, and Key3, you’d be better off defining a type with three properties, rather than using an anonymous type. Then the refactoring tools would be on your side, and you wouldn’t have reflection overhead. (The syntax wouldn’t change much, though — you’d just add the type name after new.)

Using anonymous types this way requires some work on the part of the function being called, to do the needed bits of Reflection. Eilon’s article includes sample code, although it leaves something to be desired; for example, he makes a new type for the key-value pairs, when KeyValuePair<> is already out there waiting to be used. And at that, why return a list of key-value pairs, when you could just return a dictionary?

Here’s my contribution. This version has the added advantage that you can pass in either a type with public properties (e.g. an anonymous type), or an IDictionary (generic or non-), and it does the Right Thing™. It returns a dictionary with case-insensitive key lookup, so you could use dictionary["key1"] just as well as dictionary["Key1"] (change it if that’s not what you want). Unit tests are left as an exercise for the reader.

public static IDictionary<string, TValue> ObjectToDictionary<TValue>(object o)
{
var result = new Dictionary<string, TValue>(StringComparer.InvariantCultureIgnoreCase);
if (o == null)
return result;
if (o is IDictionary)
{
foreach (DictionaryEntry entry in (IDictionary) o)
result.Add(entry.Key.ToString(), (TValue) entry.Value);
}
else
{
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(o))
result.Add(prop.Name, (TValue) prop.GetValue(o));
}
return result;
}

The above code snippet is public domain; use it how you like.

There are no responses to “C# 3.0: Dictionary parameters (like in Ruby)” yet.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy