Introduction
.NET 4 introduces a set of new features, and among them there’s a dynamic
keyword. We'll discuss usage of this keyword in this article.
What is Dynamic Keyword?
We can read in MSDN:
The type is a static type, but an object of type dynamic bypasses static type checking.
So, dynamic
can be used in 2 cases:
- For COM interop:
excelApp.Cells[1, 1].Value = "Name";
Excel.Range range2010 = excelApp.Cells[1, 1];
This is convenient and easy to understand.
- In the code: parameters in function, local variables, etc.
I want to show you the reasons why the second case should be used extra carefully, or not used at all.
Why Dynamic is Evil?
By using dynamic
in methods, you:
- Make the classes (or even libraries) more coupled (loose coupling is a fundamental principle of OO design, you can read about it, e.g. in MSDN Magazine)
- Write the code that will be possible hard to understand and change (IntelliSense will not work with it, and even Resharper will not help you). Without the author of this code, it will be almost impossible to understand.
- Create potential source of bugs that are very hard to find and fix.
Example
Let’s see an example:
Programmer A has created a class library called FooLibrary
:
Programmer B has written code that works with library FooLibrary
:
using FooLibrary;
namespace FooDemo {
class Program {
static void Main(string[] args) {
AbstractFooFactory fooFactory = new FooFactory();
AbstractFoo foo = fooFactory.ProduceFoo();
ProcessFoo(foo);
}
private static void ProcessFoo(dynamic foo) {
foo.Bar();
}
}
}
Everything was working very well, as the programmer B knows that the factory always produces instances of ComplexFoo
, or its descendant VeryComplexFoo
. Both have method Bar()
.
N days passed.
The company where programmers A and B work ordered a library ExternalFoo
. Freelancer C made this:
After that, programmer A has been asked to add a feature to FooLibrary
.
When adding a feature, he saw that the method Bar()
has no usages except of ComplexFoo
and its descendant. The programmer A marked this method as protected internal
and renamed it to NewBar()
.
The code built okay and was uploaded to the production server.
One day was spent by the company to recover from the circumstances of the error:
Unhandled Exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
'FooLibrary.VeryComplexFoo' does not contain a definition for 'Bar'
Programmer A has been dismissed from the company. He has found the problem and whacked programmer B in the face.
Programmer B has been told to fix the bug urgently. To do this, he has marked the method NewBar()
as public
and changed the call:
private static void ProcessFoo(dynamic foo) {
foo.NewBar();
}
After this, the code which used the library ExternalFoos
(created by freelancer), failed.
Programmer B has been dismissed from the company too.
Programmer C has examined the problem and found a good solution:

using FooLibrary;
namespace FooDemo {
class Program {
static void Main(string[] args) {
AbstractFooFactory fooFactory = new FooFactory();
AbstractFoo foo = fooFactory.ProduceFoo();
if (foo is ComplexFoo) {
ProcessFoo(foo as ComplexFoo);
} else {
DoSomethingElse();
}
}
private static void DoSomethingElse() {}
private static void ProcessFoo(ComplexFoo foo) {
foo.NewBar();
}
}
}
Now, if anybody refactors the code of FooLibrary
and NewBar()
method, it’s clear where this method is used. Also, after renaming this method, a solution with ExternalFoos
will not build at all, and this means that the library ExternalFoos
has not been refactored.
This example is very simple and straightforward. In the real world, there would be tons of code using dynamic
in methods. Just try to imagine that you refactor this code, this is a horror.
I really don’t understand why Microsoft has allowed using dynamic
as a parameter. Do you?
Another Negative Aspects
Here’s the code with dynamic
method:
using FooLibrary;
namespace FooDemo {
class Program {
static void Main(string[] args) {
AbstractFooFactory fooFactory = new FooFactory();
AbstractFoo foo = fooFactory.ProduceFoo();
ProcessFoo(foo);
}
private static void ProcessFoo(dynamic foo) {
foo.Bar();
}
}
}
And here’s the generated code:
internal class Program {
private static void Main(string[] args) {
ProcessFoo(new FooFactory().ProduceFoo()) }
private static void ProcessFoo([Dynamic] object foo) {
if (<ProcessFoo>o__SiteContainer0.<>p__Site1 == null) {
<ProcessFoo>o__SiteContainer0.<>p__Site1 =
CallSite<Action<CallSite, object>>.Create
(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded,
"Bar", null, typeof(Program), new CSharpArgumentInfo[]
{ CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })) }
<ProcessFoo>o__SiteContainer0.<>p__Site1.Target.Invoke
(<ProcessFoo>o__SiteContainer0.<>p__Site1, foo) }
[CompilerGenerated]
private static class <ProcessFoo>o__SiteContainer0 {
public static CallSite<Action<CallSite, object>> <>p__Site1 }
}
Let’s compare the performance, here’s the code we’ll run:
static void Main(string[] args) {
AbstractFooFactory fooFactory = new FooFactory();
AbstractFoo foo = fooFactory.ProduceFoo();
DateTime dateStart = DateTime.Now;
for (int i = 0; i < 200000000; i++) {
ProcessFoo(foo);
}
Console.WriteLine(DateTime.Now - dateStart);
}
private static void ProcessDynamicFoo(dynamic foo) {
foo.NewBar();
}
private static void ProcessFoo(AbstractFoo foo) {
ComplexFoo cmplxFoo = foo as ComplexFoo;
if (cmplxFoo == null) {
throw new InvalidOperationException();
}
cmplxFoo.NewBar();
}
If we use ProcessFoo
, the result will be 2.5 seconds.
If we use ProcessDynamicFoo
, the result will be 6 seconds.
It’s not time-critical here but dynamic is more than twice slow.
Points of Interest / Conclusion
dynamic
is cool, when it’s used for COM interop; it gives readable and simple code.
- In other cases,
dynamic
is evil and should be avoided; using dynamic
, you make modules more coupled.
History
- March 2010 - Initial revision