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.
7
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:
- method call dispatch to a dynamically bound type (like an IronPython variable)
- 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:
- Performance is number one priority.
- Static type checking is desirable for more robust runtime
- The types can be derived at compile time
- 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.
1
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).
1
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.
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
:
- 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 useobject
. - 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.