When Should One Use Dynamic Keyword in C# 4.0

What is the 'dynamic' type in C# 4.0 used for?

The dynamic keyword is new to C# 4.0, and is used to tell the compiler that a variable's type can change or that it is not known until runtime. Think of it as being able to interact with an Object without having to cast it.

dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!

Notice we did not need to cast nor declare cust as type Customer. Because we declared it dynamic, the runtime takes over and then searches and sets the FirstName property for us. Now, of course, when you are using a dynamic variable, you are giving up compiler type checking. This means the call cust.MissingMethod() will compile and not fail until runtime. The result of this operation is a RuntimeBinderException because MissingMethod is not defined on the Customer class.

The example above shows how dynamic works when calling methods and properties. Another powerful (and potentially dangerous) feature is being able to reuse variables for different types of data. I'm sure the Python, Ruby, and Perl programmers out there can think of a million ways to take advantage of this, but I've been using C# so long that it just feels "wrong" to me.

dynamic foo = 123;
foo = "bar";

OK, so you most likely will not be writing code like the above very often. There may be times, however, when variable reuse can come in handy or clean up a dirty piece of legacy code. One simple case I run into often is constantly having to cast between decimal and double.

decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");

The second line does not compile because 2.5 is typed as a double and line 3 does not compile because Math.Sqrt expects a double. Obviously, all you have to do is cast and/or change your variable type, but there may be situations where dynamic makes sense to use.

dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");

Read more feature : http://www.codeproject.com/KB/cs/CSharp4Features.aspx

Is the use of dynamic considered a bad practice?

The short answer is YES, it is a bad practice to use dynamic.

Why?

dynamic keyword refers to type late binding, which means the system will check type only during execution instead of
during compilation. It will then mean that user, instead of programmer, is left to discover the potential error. The error could be
a MissingMethodException, but it could be also a not intended call to an existing method with a bad behavior.
Imagine a call to a method that ends in computing a bad price or in computing a bad level of oxygen.

Generally speaking, type checking helps to get deterministic computing, and so, when you can, you should use it. Here's a question on shortcomings of dynamic.

However, dynamic can be useful...

  • Interop with COM like with Office
  • Interop with languages where dynamic types are part of the language (IronPython, IronRuby) as dynamic was introduced to help porting them to .Net.
  • Can replace reflection complex code with low ceremony, elegant code (however depending on the case, you still should profile both approaches to check which one is the most appropriate in terms of performance and compile-time checks).

Code base is evolving throughout the application life cycle and even if dynamic seems ok now,
it set a precedent which can implies an increase of dynamic keyword usage by your team. It can lead to increased
maintenance costs (in case the above stated signature evolves, you can notice it too late). Of course, you could
rely on unit tests, non regression human tests and so on. But when you have to choose between human discipline related
quality and automatically checked by computer related quality, choose the later. It's less error prone.

In your case...

In your case, it seems you can use the common inheritance scheme (the first one below and the one you mention in your question),
as dynamic won't give you any additional benefit (it will just cost you more processing power and make you incurring
the risk of future potential bugs).

It depends on whether you can change code of MyClass hierarchy and/or Caller.InvokeMethod.

Let's enumerate
the different possible alternatives to dynamic...

  • Compiled type-checked alternative to dynamic keyword method call:

The most common is using interface virtual call like this instance.InvokeMethod() with inheritance calling the right implementation.

public interface IInvoker : { void InvokeMethod(); }
public abstract class MyBaseClass : IInvoker { public abstract void InvokeMethod(); }
public class MyAnotherClass : MyBaseClass { public override void InvokeMethod() { /* Do something */ } }
public class MyClass : MyBaseClass { public override void InvokeMethod() { /* Do something */ } }

Another a little less performant is by using Extension Methods

public static class InvokerEx:
{
public static void Invoke(this MyAnotherClass c) { /* Do something */ } }
public static void Invoke(this MyClass c) { /* Do something */ } }
}

If there are several "visitors" of MyBaseClass hierarchy, you can use the Visitor pattern:

public interface IVisitor 
{
void Visit(this MyAnotherClass c);
void Visit(this MyClass c);
}

public abstract class MyBaseClass : IInvoker { public abstract void Accept(IVisitor visitor); }
public class MyAnotherClass : MyBaseClass { public override void Accept(IVisitor visitor) { visitor.Visit(this); } }
public class MyClass : MyBaseClass { public override void Accept(IVisitor visitor) { visitor.Visit(this); } }

Other variants though not very useful here (Generic method) but interesting for the performance comparison:

public void InvokeMethod<T>(T instance) where T : IInvoker { return instance.InvokeMethod(); }
  • Dynamic alternative to dynamic keyword method call :

If you need to call a method not known at compile time, I've added below the different techniques you could use and updated the performance results:

MethodInfo.CreateDelegate

        _method = typeof (T).GetMethod("InvokeMethod");
_func = (Func<T, int>)_method.CreateDelegate(typeof(Func<T, int>));

Note: Cast to Func is needed to avoid call DynamicInvoke (as it is generally slower).

DynamicMethod and ILGenerator.Emit

It actually build the full call from scratch, it's the most flexible but you must have some assembler background to fully appreciate it.

        _dynamicMethod = new DynamicMethod("InvokeMethod", typeof (int), new []{typeof(T)}, GetType().Module);
ILGenerator il = _dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, _method);
il.Emit(OpCodes.Ret);
_func = (Func<T, int>) _dynamicMethod.CreateDelegate(typeof (Func<T, int>));

Linq Expression

It's similar to DynamicMethod, however you don't control the IL generated. Though, it's really more readable.

        _method = typeof (T).GetMethod("InvokeMethod");
var instanceParameter = Expression.Parameter(typeof (T), "instance");
var call = Expression.Call(instanceParameter, _method);
_delegate = Expression.Lambda<Func<T, int>>(call, instanceParameter).Compile();
_func = (Func<T, int>) _delegate;

MethodInfo.Invoke

The last but not the least, the standard known reflection call.
However, even if it's easy to mess with it, don't use it as it's really a bad performer (look at the benchmark results). Prefer CreateDelegate which is really faster.

        _method = typeof (T).GetMethod("InvokeMethod");
return (int)_method.Invoke(instance, _emptyParameters);

Code of the benchmark test can be found on GitHub.

Benchmark of the different methods to get an order of magnitude (for 10 Millions of call) (.NET Framework 4.5):

For Class standard call:
Elapsed: 00:00:00.0532945
Call/ms: 188679
For MethodInfo.CreateDelegate call:
Elapsed: 00:00:00.1131495
Call/ms: 88495
For Keyword dynamic call:
Elapsed: 00:00:00.3805229
Call/ms: 26315
For DynamicMethod.Emit call:
Elapsed: 00:00:00.1152792
Call/ms: 86956
For Linq Expression call:
Elapsed: 00:00:00.3158967
Call/ms: 31746
For Extension Method call:
Elapsed: 00:00:00.0637817
Call/ms: 158730
For Generic Method call:
Elapsed: 00:00:00.0772658
Call/ms: 129870
For Interface virtual call:
Elapsed: 00:00:00.0778103
Call/ms: 129870
For MethodInfo Invoke call:
Elapsed: 00:00:05.3104416
Call/ms: 1883
For Visitor Accept/Visit call:
Elapsed: 00:00:00.1384779
Call/ms: 72463
== SUMMARY ==
Class standard call: 1
Extension Method call : 1,19
Generic Method call : 1,45
Interface virtual call : 1,45
MethodInfo.CreateDelegate call : 2,13
DynamicMethod.Emit call : 2,17
Visitor Accept/Visit call : 2,60
Linq Expression call : 5,94
Keyword dynamic call : 7,17
MethodInfo Invoke call : 100,19

EDIT:

So comparing to Visitor pattern, dynamic dispatch is just about 3 times slower. It can be acceptable for some applications as it can remove cumbersome code. It's always up to you to choose.
Just keep in mind all the drawbacks.


EDIT: (as an answer to multiple dispatch benefit)

Using trendy pattern name like 'multiple dispatch' and just state that it's cleaner because it uses less code, doesn't make it an added benefit IMHO.
If you want to write trendy code or don't care about type safety and production stability, there are already a lot of language out there offering full feature dynamic typing. I see dynamic keyword introduction in C# as a way to close the gap between the strong typed language family and not so strongly typed other languages. It doesn't mean you should change the way you develop and put type checks to trash.

UPDATE: 2016/11/08 (.NET Framework 4.6.1)

Orders of magnitude remain the same (even if some of them have improved a bit):

Class standard call: 1
Extension Method call : 1,19
Interface virtual call : 1,46
Generic Method call : 1,54
DynamicMethod.Emit call : 2,07
MethodInfo.CreateDelegate call : 2,13
Visitor Accept/Visit call : 2,64
Linq Expression call : 5,55
Keyword dynamic call : 6,70
MethodInfo Invoke call : 102,96

C# Practical usage of the dynamic keyword

Here a good article:

As a developer, you use the dynamic
keyword with variables expected to
contain objects of uncertain type such
as objects returned from a COM or DOM
API; obtained from a dynamic language
(IronRuby, for example); from
reflection; from objects built
dynamically in C# 4.0 using the new
expand capabilities.

Using the Dynamic Keyword in C# 4.0

Advantages and Disadvantages of C# 4.0 'dynamic' keyword?

Not exactly var vs dynamic but the following SO link discuss reflection vs dynamic. Check Out : dynamic vs Var/Object/reflection

C#4 dynamic keyword - why not?

Some see it as a tool that will be abused. Like "Option Strict Off" and "On Error Resume Next" in VB which "pure" languages like C# and Java have never had.

Many said the same about the "var" keyword, yet I don't see it being abused, once it became understood that it wasn't the same as VB's "Variant"

It could be abused in places that lazy developers don't want type checking on classes and just try catch dynamic calls instead of writing "if blah is Blah ...".

I personally feel it could be used properly in situations like this recent question that I answered.

I think the ones really understanding it's power are those heavily into the dynamic .NET languages.

C# 'dynamic' keyword... is it really a RESERVED keyword or just a identifier that means something special when used as type?

dynamic is a contextual keyword as of C# 4.0. The fourth edition of the ECMA C# spec does not refer to C# 4.0. (Note the 2006 publication date.)

MSDN describes it as a keyword.

It's also in this table of contextual keywords. (Scroll down.)

dynamic keyword problem

Dynamic keyword was introduced as part of C# 4.0 language - the compiler comes with VS 2010. Its a language feature and does not need runtime support (AFAIK) hence once complied with C# 4.0 compiler, shouldn't have any issue with earlier version of runtime. Changing target framework in VS 2010 does not switch the compiler (which remains at 4.0) - we will receive compiler error only if you use feature that targets new library or runtime. For example, in VS 2008, you could use lambda expressions or var keyword for target runtime 2.0 but extension methods were not available because extension attribute was part of 3.5 assembly.

EDIT: Above is wrong - dynamic keyword requires Framework 4.0. I couldn't even compile in VS2010 when target fx was changed to 3.5. I believe that OP might not have used the dynamic var later in the code so that compiler optimization would have removed it making OP believe that its working.

Is it a bad idea to use the new Dynamic Keyword as a replacement switch statement?

It really depends on what you consider a "good idea".

This works, and it works in a fairly elegant manner. It has some advantages and some disadvantages to other approaches.

On the advantage side:

  1. It's concise, and easy to extend
  2. The code is fairly simple

For the disadvantages:

  1. Error checking is potentially more difficult than a classic visitor implementation, since all error checking must be done at runtime. For example, if you pass visitorTest.DynamicVisit(4.2);, you'll get an exception at runtime, but no compile time complaints.
  2. The code may be less obvious, and have a higher maintenance cost.

Personally, I think this is a reasonable approach. The visitor pattern, in a classic implementation, has a fairly high maintenance cost and is often difficult to test cleanly. This potentially makes the cost slightly higher, but makes the implementation much simpler.

With good error checking, I don't have a problem with using dynamic as an approach here. Personally, I'd probably use an approach like this, since the alternatives that perform in a reasonable manner get pretty nasty otherwise.

However, there are a couple of changes I would make here. First, as I mentioned, you really need to include error checking.

Second, I would actually make DynamicVisit take a dynamic directly, which might make it (slightly) more obvious what's happening:

class VistorTest
{
public string DynamicVisit(dynamic obj)
{
try
{
return Visit(obj);
}
catch (RuntimeBinderException e)
{
// Handle the exception here!
Console.WriteLine("Invalid type specified");
}
return string.Empty;
}

// ...Rest of code

What's the difference between dynamic (C# 4) and var?

var is static typed - the compiler and runtime know the type - they just save you some typing... the following are 100% identical:

var s = "abc";
Console.WriteLine(s.Length);

and

string s = "abc";
Console.WriteLine(s.Length);

All that happened was that the compiler figured out that s must be a string (from the initializer). In both cases, it knows (in the IL) that s.Length means the (instance) string.Length property.

dynamic is a very different beast; it is most similar to object, but with dynamic dispatch:

dynamic s = "abc";
Console.WriteLine(s.Length);

Here, s is typed as dynamic. It doesn't know about string.Length, because it doesn't know anything about s at compile time. For example, the following would compile (but not run) too:

dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);

At runtime (only), it would check for the FlibbleBananaSnowball property - fail to find it, and explode in a shower of sparks.

With dynamic, properties / methods / operators / etc are resolved at runtime, based on the actual object. Very handy for talking to COM (which can have runtime-only properties), the DLR, or other dynamic systems, like javascript.



Related Topics



Leave a reply



Submit