C# 4.0 Dynamic and No More Annoying Casts

February 23, 2010 18:05 | Uncategorized

I have a strong distaste for things that works in a way that I dislike. I am very unique that way.

Right at the top of that list is any time that I am forced by language limitations into redundant code. Notably, casting. Take the following for example:

var dictionary = new Dictionary();
dictionary["name"] = "Snoopy";
dictionary["number"] = 8;
int dictinary["number"] = (int)dictionary["number"]

That last line bothers me a lot. I already told you that I expect an integer on the left hand side, why do I have to cast too?!.

Last night I thought I had it figured out. The get by index handler would return a new “TypedObject” instance which would then contain an implicit converter that would do all the casting for us. However, due to the hopelessly (and stupidly) limited nature of the implicit operator this was a no-starter.

Half an hour after I went to bed defeated, I leaped back out of bed full of vigor and brainy-ness. With hands trembling I made my changes and ran my tests:

[TestClass]
public class When_retrieving_from_TypedDictionary {
  TypedDictionary _dictionary;
  MemoryStream _stream = null;
  [TestInitialize]
  public void Setup() {
    _dictionary = new TypedDictionary();
    _dictionary.Add("DateTime", DateTime.Parse("01/01/2010"));
    _dictionary.Add("String", "hello friends");
    _stream = new MemoryStream();
    _dictionary.Add("MemoryStream", _stream);
  }
  [TestMethod]
  public void can_get_datetime() {
    DateTime dt = _dictionary["DateTime"];
    Assert.AreEqual(DateTime.Parse("01/01/2010"), dt);
  }
  [TestMethod]
  public void can_get_string()  {
    string str = _dictionary["String"];
    Assert.AreEqual("hello friends", str);
  }
  [TestMethod]
  public void can_get_reference_type() {
    MemoryStream stream = _dictionary["MemoryStream"];
    Assert.AreSame(_stream, stream);
  }
  [TestMethod]
  public void dont_need_to_cast_at_all() {
    Assert.AreSame(_stream, _dictionary["MemoryStream"]);
  }
}

They passed!

I’m a genius! I’ve figured out how to do something nobody ever had before!

Well not really, though it is an unexpected application of a C# language feature. You see, at my new job at EPS we’re using C# 4.0 on a project. As we all know the biggest hullabaloo with C# 4.0 is the introduction of the unassuming dynamic keyword. Honestly, as a fan of dynamic languages like javascript and ruby I’ve been concerned that I would abuse it and always abstained – it doesn’t do anything that you couldn’t do with a dictionary after-all.

Well, it can do one thing – implicit type-casting! So presenting, the above mentioned (and dead-simple) TypedDictionary:

public class TypedDictionary {
  readonly Dictionary _storage = new Dictionary();
  public dynamic this[string key] {
  get { return _storage[key]; } }
  public void Add(string key, object obj) {
    _storage[key] = obj;
  }
}

It works, I promise. How awesome is that?

kick it on DotNetKicks.com

Comments

So you can only store 1 value per type? That’s not very dictionary-ish of you.

/ Fritz
February 23, 2010, 21:52

@Fritz,

No, not at all. It’s a wrapper for a normal dictionary, the keys that I use are just so its easy to track through the demo. Take my code and give it a shot. You could just as well call

_dictionary.Add(”some-key”, “some value”);
string someVar = _dictionary["some-key"]

Heck, you could even use this as an extension method to a normal IDictionary

public dynamic Get(this IDictionary dictionary, string key) {
return dictionary[key];
}
var d = new Dictionary
();
d["string-key"] = “a string”;
d["float-key"] = 123.03f;
string s = d.Get(”string-key”);
float f = d.Get(”float-key”);

/ togakangaroo
February 23, 2010, 22:34

Write a comment: