My question is about whether what follows is an appropriate use of the dynamic
keyword in C# 4.
I have some helper methods that provide a more useful representation of various objects than their standard ToString
methods do, which I use for unit testing. Here is a simplified example:
public static string PrettyPrint<T>(IEnumerable<T> list)
{
return string.Join(", ", list);
}
// Needed because string is IEnumerable<char>, to prevent
// "Hello" -> "H, e, l, l, o"
public static string PrettyPrint(string s)
{
return s;
}
public static string PrettyPrint(object o)
{
return o.ToString();
}
I use them something like this:
public static void PrettyPrinting()
{
object[] things = { 1, "Hello", new int[] {1, 2, 3} };
foreach (dynamic item in things)
{
Console.WriteLine(PrettyPrint(item));
}
}
This produces the following output:
1
Hello
1, 2, 3
Notice that if I replace the dynamic
keyword with object
, I get the following (all the calls are routed through PrettyPrint(object)
), which is what I am trying to avoid:
1
Hello
System.Int32[]
So my question is essentially is this a code smell or is it legitimate to cast an object
to dynamic
in this way?
So long as you don't abuse it, duck typing like this is part of the reason dynamic
was added to the language.
As to your question, I'm not 100% sure as I don't know your teams style of coding. (I also see little comments ;) )
DuckTyping has it's uses - however a developer needs to know what they're doing before using it. Otherwise it's like running with scissors; it could be abused like other keywords in the C# system.
Personally, I'd rather see extension methods, but depending on the developer, his/her arguments and the documentation done I'd probably allow it.
The biggest reason for my hesitation (and this example is pretty tame to some of the ones I've seen online) is it stops you from finding issues at compile time. It requires more QA testing, a lot more boundary testing, and has a higher risk of failure.
Not an answer to the exact question, but I would say your code is not very OO, which is another smell.
Ideally you want to call item.PrettyPrint()
and each item is supposed to return its representation, and override PrettyPrint
.
Luckily, existing types can be extended with extension methods. They enable you to add the methods and that's what I would do instead.
If you still want to have the logic for the display of each type in one class, I would combine extension methods with the visitor pattern.
That said, I don't have C# environment so I can't test what I propose. Let me know if you try this, and if it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With