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.
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
No comments:
Post a Comment