3

I'm making a class similar to the following:

public class KeyValue
{
    public readonly string key;
    public readonly object value;
}

Value could be of any object type as a result of this design.

Alternatively, I could just use dynamic for value and it'll make my life easier, because it would mean no type-casting, and also because, as far as I understand, I could use value types without needing to box/unbox.

Is there any reason not to use dynamic and to use object instead? Because I can't think of any.

Note: I realize generics are much more suited for this, but it doesn't work for my needs. The above is really a simplification just for the purposes of this question.

closed as unclear what you're asking by gnat, user53019, World Engineer Sep 18 '14 at 21:41

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Because of the extra stuff involved with dynamic, I usually frame the question the other way around: do I really need to use dynamic? Although there are times where you need to do what you have listed, sometimes this can also be a design smell. Can you tell us why generics weren't working for you? – J Trana Sep 18 '14 at 1:28
  • 1
    Gah, I guess I should've given a better example. My problem with generics is that it makes working with interfaces harder and inflexible. Judging from the answers I'm seeing, it seems that perhaps I should read more about generics before abusing dynamic. – 9a3eedi Sep 18 '14 at 6:05
  • 1
    Strong types are definitely a double-edged sword. – J Trana Sep 18 '14 at 6:06
  • 1
    You are aware that interfaces can handle generics quite easily? Generic constraints can also make your life easier as well (i.e. you should definitely experiment with them). – Stephen Sep 18 '14 at 6:12
  • I think I need to re-ask the question. I guess I'll just accept the best answer for this question in its current form – 9a3eedi Sep 18 '14 at 6:23
15

If you can't think of a good reason TO use dynamic, then you are foregoing potential compile time checks for little to nothing in return.

I prefer generics over object, and prefer object over dynamic, unless I need to interact with a dynamic language ScriptEngine or a dynamic container like a web form where its reasonable to handle the potential runtime exceptions when I access a missing field. Generics will perform best; and with object, you are at least signifying your intentions are to store any sort of object in the same container.

Dynamic is not an actual type, and it isn't "object" so it should never be used to mean "any sort of object", it should actually be used when you know what the object's contract is (method/property signature's); it is a runtime dispatch vehicle for keeping the same, convenient syntax for a type-unsafe (or at least dynamically bound) activity. It's like saying:

"OK, I know the activity I'm doing is subject to runtime dispatch and runtime errors, so give me the syntactical sugar anyway"

When I see dynamic, I usually assume there is an imminent:

  1. method call dispatch to a dynamically bound type (like an IronPython variable)
  2. access to dynamic form data with property syntax in an MVC controller

Though another legit use for it is to use the dynamic dispatch capability to implement the Visitor Pattern, although traditional virtual methods are likely faster.

class FooVisitor {
     void Accept(Expression node) { ... }
     void Accept(Statement node) { ... }
}

foreach(dynamic node in ASTNodes) {
    visitor.Accept(obj);  // will be dispatched at runtime based on type of each obj
}

Don't use it when:

  1. Performance is numero uno
  2. Static type checking is desirable for more robust runtime
  3. The types can be derived at compile time
  4. A generic type will do

If used unnecessarily, dynamic can actually reduce the robustness of your code by changing C# to a dynamic scripting language.

  • I would also add that I prefer anonymous types in C# to dynamic, where possible, as these are more specific than object and yet retain compile-time safety. – Michael Sep 18 '14 at 14:22
5

dynamic was primarily introduced as a way to allow C# to interop with languages such as Python, which is not statically typed. If you are using it out of this context you are probably forgoing functionality.

As you said, in the limited context that you present, you are much better off using generics (the KeyValuePair class looks pretty much like what you are trying to create here).

  • This explains why a lot of dynamic examples I see online involve python or web-based code. Makes sense – 9a3eedi Sep 18 '14 at 6:08
3

The answer is that if dynamic types make your code better, produce a better outcome and make your life easier then of course you should use them. That's what they're for!

You should absolutely not concern yourself with boxing/unboxing, which is pretty efficient apart from imposing some load on the garbage collector. Look at the generated code for dynamic types and you'll see significantly higher overheads, but you shouldn't worry about those either.

The challenge in this game is to produce correct code that you and other people can understand and work with. Use generics if you can, dynamic if it works for you and raw objects if you have to. Then benchmark before you optimise. Or just move on.

0

If you're using object as a variable type, and you're really sure that you need to, and you're really sure that generics won't do what you need, there is one and a half scenarios that I've encountered where you should not use dynamic:

  1. You need to deploy to old machines. Dynamic is only available with .NET 4.0, so if you need to support machines that aren't guaranteed to have it... just use object.
  2. And along similar lines, Xamarin (as of a few months ago when I was keeping track of it) did not yet have stable support for dynamics. This kinda falls in with #1 - essentially, if your target platform doesn't support them, then don't use them.

That's variables though. dynamic as a function parameter causes the function to be dynamically dispatched. This is usually what you want, but not always. Using object will use normal instance-only dispatch. Otherwise, the same guidelines apply.

Not the answer you're looking for? Browse other questions tagged or ask your own question.