Monday 14 November 2011

Living in a "dynamic" C# world

Taking a brief break from the C++11 posts (I'm working on the next one, I promise), I thought I'd quickly cover a small problem I came up against in C# and how something I'd previously dismissed really helped me out.  If you want to try out any of the code below I'd strongly recommend looking at LinqPad which is a great tool for trying out sample code, expressions and for querying your databases using Linq.

I can't remember the number of times I've looked at the new "dynamic" keyword and thought of it as ugly, and I will admit that maybe I've not been it's greatest advocate.  Recently however I went on a training course during which we spent some time calling IronPython scripts from C#, so I could see a use for dynamic, but not so much outside of this use-case.

Today however I encountered a problem and the dynamic keyword came to my rescue.  The problem was this; I'm loading in data from an XML document (and no, XML is not my problem), this document has a number of sections which identify how to check something from another document, so it might have an entry which says "You're expecting a value in a field called 'x' of type 'y' and I want to check it like this...".  So as an example, say I'm picking up a value which is a double precision value, and I want to check it against another value of the same type but using a tolerance.  So if 's' is my source value, 'x' is my expected value and 't' is my delta then I would want to check it using the following:

// |s - x| < t
var s = 1.0005;
var x = 1.0004;
var t = 1.0001;

return Math.Abs(s - x) < t;

Great, but here's the problem, when I'm writing the code the function first needs to check the type and convert it from a string value to the correct type, which I only know about because the type is held in another variable.  Again, not too tricky as I can just write the following (where "type" is a Type variable holding the type I need to use):

var convertedValue = Convert.ChangeType(s, type);

The compiler has no problem with this and lets me carry on my merry way, but when I add the following line the compiler starts to shout and tells me I'm an idiot for even attempting to apply an operand of "-" to a type of "object" and "object"!

var sourceValue = "1.0005";
var expectedValue = "1.0004";
var tolerance = 1.0001;
var type = typeof(double);

var convertedSource = Convert.ChangeType(sourceValue, type);
var convertedExpected = Convert.ChangeType(expectedValue, type);
var result = Math.Abs(convertedSource - convertedExpected) < tolerance;

Console.WriteLine(result);

The thing is, I know that my converted values are doubles but I need to tell the compiler that I know what I'm doing here and it can compile this.  Well this is where "dynamic" comes to save the day, it allows me to bypass compile-time type checking and instead have this checked at run-time.  So changing the code to the following:

var sourceValue = "1.0005";
var expectedValue = "1.0004";
var tolerance = 1.0001;
var type = typeof(double);

dynamic convertedSource = Convert.ChangeType(sourceValue, type);
dynamic convertedExpected = Convert.ChangeType(expectedValue, type);
var result = Math.Abs(convertedSource - convertedExpected) < tolerance;

Console.WriteLine(result);

I get the expected result of "True" when I run the code.

I know there are probably other ways of doing this, and the example code I've presented doesn't exactly portray the complexity I was attempting to deal with, but I do think it's quite a nice little solution.  Hopefully after reading this you might also re-consider looking at the "dynamic" keyword, you never know when you might have a genuine use for it.

Creative Commons Licence
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

No comments:

Post a Comment