C# 4.0 introduces the new 'dynamic' keyword to the language, adding dynamic support to the .NET Framework though the DLR (Dynamic Language Runtime).
My first understanding of the use of such a dynamic support was the following:
- Great to use for inter-connections with dynamic langages, avoiding to have to write too complex code to bridge the gap between the 2 languages.
- Great to use for instance for Microsoft Office automation. MS Office automation is done though COM objects. Previous use of MS Office PIA was cumbersome. The new dynamic keyword makes much less verbose.
- Enhance support for reflection.
With the dynamic keyword, type checking is no more done at compile time but will be done at runtime. Thus making code writing more flexible (especially when using uncertain type, only known at runtime). However it makes writing code less safe (no compile checking) and less productive (no intellisense). Therefore one should not use the dynamic keyword in C#, except in previous cases. And use instead Object orientation design principles and patterns to achieve safe, strongly-typed coding. Moreover, the addition of generics to the .NET Framework 2.0 was a huge step forward to enable better object orientation and strong typing.
So IMHO the dynamic keyword and DLR is a great thing to have but will also be an added opportunity to write bad code and break core design principles. So one should be aware of it and use it sparingly, when making real sense!
Moreover be aware that the use of the dynamic keyword has a performance hit: because runtime discovery and type checking has to be done at runtime.
I came accross a post from Peter Ritchie highlighting another great use of the dynamic keyword. I said previously that when developing in C#, you should use as much as possible proper object orientation principle and patterns to write proper good code (because C# is a OO language). However there are cases where it is not easy to write full pure object oriented code. And Peter describes one of these cases and how the dynamic keyword can help:
The case is the following (for more details please refer to Peter Ritchie's post):
When you use method overloading to define methods that take different flavors of a given type hierarchy (Circle and Square both derive from Shape):
public static void Draw(Circle circle) { //... } public static void Draw(Square square) { //... }
When you want to call the Draw method, you have to call it with an object that is known at compile time to be either a Circle or a Square (or inheriting from Circle or Square). You cannot call it generically with a object of type Shape. This is because the compiler must know which method overload to link to.
Please note that this example is probably not the best as a solution could be to define the Draw method on the Shape class and override it on both Circle and Square. However there are cases where this scenario really makes sense, so just take this as a sole demonstration purpose, and get the idea of what the dynamic keyword could bring.
Back to our example, the following method will not compile:
public void ProcessShape(Shape shape) { //... Draw(shape); //... }
You instead have to write something like
public void ProcessShape(Shape shape) { //... if (!ReferenceEquals(null, shape as Square)) { Draw(shape as Square); } if (!ReferenceEquals(null, shape as Circle)) { Draw(shape as Circle); } //... }
Thus wasting the interest of object orientation, adding a maintenance point for when new Shape types are added etc...
Solution with using the dynamic keyword is:
public void ProcessShape(Shape shape) { //... dynamic dynShape = shape; Draw(dynShape); //... }
The type checking done previously in code is now done by the DLR and the code is more robust: we have elimintated the maintenance point.
And here is the full code that demonstrate the use of the dynamic keyword (just create a Console app to include this code):
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { public class Shape { } public class Circle : Shape { } public class Square: Shape { } class Program { static void Main(string[] args) { Shape myShape = null; myShape = new Square(); ProcessShape(myShape); myShape = new Circle(); ProcessShape(myShape); Console.ReadLine(); } static void ProcessShape(Shape shape) { //Draw(shape); dynamic dynShape = shape; Draw(dynShape); } static void Draw(Square square) { Console.WriteLine("I am a Square"); } static void Draw(Circle circle) { Console.WriteLine("I am a Circle"); } }
}
This is a great use of the dynamic keyword. However: this is also a good example to show that the dynamic keyword could be used improperly instead of a right object oriented design: We said before that in this specific case, it could probably better to add a Draw method on the Shape class and override it on derived class : this is a basic OO design principle: classes embed data and behavior. Thing is there is no definite rule: depending on your overall design and architecture (and especially the level of coupling you want to have), it could be good design to have the Draw method excluded from the Shape class. So nothing replaces experience, however the enhancement of the programming languages will add more and more confusion for beginners! And this makes the software design and development really challenging and exciting!
I noticed a couple of common misconceptions in this post. First, dynamic languages (including 'dynamic' in C#) are typically safer than static languages precisely because all operations are confirmed and yield meaningful language-level error messages (as opposed to segv or some machine/OS level error). Of course, with the new breed of static languages such as Java and C#, you do get safer code often with good error messages. Second, there was the suggestion that dynamic languages (and C#'s 'dynamic') is unsafe due to a lack of strong typing. Again, dynamic languages are often more strongly typed that static languages, and therefore safer.
There is nothing about C#'s 'dynamic' that is unsafe or weakly typed; it is simply not statically typed at compile-time.
Cheers,
Bill
Posted by: Bill | 03/06/2010 at 19:29
Hello Bill,
Thanks for your comments. You make a good point and I agree with you that dynamic langages are type safe and strongly-typed since type checking is done, and done at runtime.
When I say that C# without dynamic extensions produces more robust code than using dynamic extensions, I mean it because you have the extra compilation time checking that tells you immediately if you did something wrong. With dynamic extensions you have to wait exectution time to have some feedback. Or: you have to produce enough unit test code to properly early report errors.
In short, I don't want to say statically typed languages and better or worth than dyanmically typed langages. I am just saying that C# is a statically typed langage, thus using the dynamic keyword should be limited to very specific scenarios. My intent was to describe one of this scenarios.
Cheers,
Posted by: Walter Almeida | 04/06/2010 at 09:19
I will look forward your opinion about ruby on rails. Another language that used object oriented priciple
Posted by: Ruby on Rails | 25/01/2011 at 03:57