Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good practice to cast objects to dynamic so the correct overloaded method is called?

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?

like image 911
Matthew Strawbridge Avatar asked Nov 25 '11 17:11

Matthew Strawbridge


3 Answers

So long as you don't abuse it, duck typing like this is part of the reason dynamic was added to the language.

like image 64
Adam Rackis Avatar answered Sep 20 '22 03:09

Adam Rackis


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.

like image 42
Ryan Ternier Avatar answered Sep 19 '22 03:09

Ryan Ternier


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.

like image 41
ewernli Avatar answered Sep 22 '22 03:09

ewernli