Introduction
As is well known, C# has always able to squeeze into the top 10 in the nearly 10 years of programming language ranking list. On the whole, the support of C# has been towards an upward trend. There are many factors at play that result in C# achieving such performance. Among these factors, the most attractive and impressive one should be the language's forging ahead feature (see Figure 1).
Figure 1: The innovation features in various C# versions

As is indicated in the figure, in the latest C# 4.0 released in 2010, the biggest innovation is having introduced a dynamic programming language feature. In this article, we are going to explore this new and main feature, as well as other related interesting questions.
The Resurgence of Dynamic Programming Language
Dynamic programming language is not a new thing. Long before the object-oriented programming language became the mainstream, people had been used to develop applications using dynamic programming languages. Even in the prosperous time of Java, C#, C, and other object-oriented programming languages, dynamic programming languages have been "quietly" conquering new territories, occupying considerable development areas. For example, JavaScript has become the de facto dominant language in the Web client side.
In recent years, dynamic programming languages, such as Python and Ruby, have become increasingly popular. They are so active that more and more users have been attracted.
Thus, it is natural that some of the issues rise: 1. why do we need to develop the applications using dynamic programming languages? 2. Compared with C# and Java, the already mature and powerful static programming languages, what are the advantages in dynamic programming languages?
Simply put, manufacturing applications using a dynamic programming language has the following advantages.
Support REPL (Read-evaluate-print Loop)
The whole process is very much clear and concise, going straight into the problem.
Let's consider a simple example. Figure 2 shows the running-time snapshot using IronPython to compute the product of "1*2*3*...*10".
Figure 2: A simple example to use IronPython

NOTEIronPython is an open sourced dynamic language. You can download it at http://ironpython.codeplex.com.
As is seen from Figure 2, we can quickly create the computing code, and then we can immediately see the results.
If you use C# to finish the above computation, there is more trouble. You must first create a project using Visual Studio, and then add a class, write a method in the class to complete the function of the sum, and then create the code to call this method. Finally, you have to compile the project, run the result .exe file, and then you get the desired result.
Obviously, for those short tasks, the dynamic programming language with the REPL development model has great appeal.
Convenient expansion
Developers can adjust the code at any time. Whatever functions are required just directly add them to the dynamic object, while whenever they are not needed remove them. And that, such changes can take effect immediately, not needing to modify the definition and declaration as C#; and also, only when the new method is successfully compiled can it be used again.
In other words, in using a dynamic programming language, the iterative development process is pretty quick and clear-cut.
Type parsing is done at run time
Type analysis in dynamic programming languages is completed at the running time, without much unnecessary type conversion code. So, compared with the static programming languages, code written using dynamic programming languages is often more compact, less volume.
At the same time, dynamic programming languages have two major weaknesses:
(1) Many errors in the code can be found out until runtime, as well as require a specific runtime environment support. So, testing it is not convenient, nor is it difficult to support many of the various software engineering tools that are used to improve the quality of the code. Therefore, dynamic programming language is not suitable for developing larger-scaled, complex logic applications.
(2) Compared with the static programming languages, dynamic programming language programs bear low performance. However, with continual development of computer hardware and software technology, such as extensive use of multi-core CPU, optimization of dynamic programming language engine and runtime environment, application performance written with dynamic programming language continues to improve, in particular contexts, even comparable to that in the static programming language.
Dynamic Programming Feature in C# 4
In order to have programming languages, such as C#, Visual Basic.NET, bear dynamic programming language features, .NET 4.0 introduces DLR (Dynamic Language Runtime)", as shown in Figure 3.
Figure 3: The Dynamic Language Runtime component in .NET 4.0 frameworks

As shown in Figure 3 above, DLR runs on top of CLR, providing a dynamic language runtime environment, allowing applications based upon Python, Ruby and other dynamic languages to run on NET platforms; and, at the same time, the existing .NET static typed programming languages, such as C# and Visual Basic.NET, can also use DLR and has some of the characteristics of dynamic programming languages.
Write dynamic code using C# 4.0
C# 4 has introduced a new keyword - dynamic, with which you can write "dynamic" code.
For example, the following code creates an ExpandoObject object (which must be defined as dynamic):
Note that to use the ExpandoObject object, you have to add the following directive first:
Now, let's go a further step to look at the declaration of the class ExpandoObject, as follows:
Well now let's continue to discuss the ExpandoObject object. The specialty of the above ExpandoObject is that we can add new members to it on the fly:
The usage of these newly-added dynamic members is the same as common class members:
As indicated above, the ExpandoObject object implements the IDictionary<string,object> interface, which can be regarded as a dictionary object. Hence, all members dynamically added to the dictionary are elements of this dictionary object, which means we can not only add new members, but can remove members that are no longer required at any time:
After the method FakeMethod gets removed, the system will throw a RuntimeBinderException exception when you try to access this method again.
Simplify interactions with COM components
As is well known, to invoke the COM components in the non-managed world from the managed .NET, we must fall back upon the Interop Assembly as a bridge, which defines the corresponding type mappings between CLR and COM.
So, by adding references to the related "Interop Assemblies", you can create various types of instances of (i.e. COM wrapper objects) contained in these assemblies in your .NET applications. And further, the method calls (or property accesses) to these objects will be forwarded to the corresponding COM components.
To call Microsoft Word, for example, before C# 4.0 you may often need to write code like this:
Above, the Open() method call statement can only be described using the term "terrific", because the Open() method defined in the Word component involves too many parameters.
In C# 4, however, to use the dynamic keyword, together with the other two newly-added features - named parameters and optional parameters, you can write more concise code like the following:
In the above code, non-required parameters are eliminated; and also, the ref keyword before parameters can be removed.
When the above code runs, DLR will resort to the reflection technique to bind the dynamic expression to the proxy object - Word.Application contained in the COM interop assembly.
A further step into C# 4 Dynamic Programming
In conclusion, the dynamic variables defined in C# 4 can refer to the following types of objects:
- Traditional "static" CLR objects.
- COM wrapper objects, as already described just a minute ago.
- Dynamic objects that implement the IDynamicMetaObjectProvider interface. ExpandoObject is an instance of such type of object.
- The objects created using DLR-based dynamic languages (such as IronRuby and IronPython).
From the perspective of C# programmers, all the four objects are the same. In another work, they all can be referenced through a dynamic variable, and in turn, DLR, at runtime, dynamically binds the method calls and field access request to the real target object.
Up till this point, we can draw such a conclusion: the dynamic function is supported by DLR while is the fruit from the cooperation between C # compiler and DLR.
Please consider the following example code:
C# compiler, in dealing with the above code, will not check whether the variable d can support auto increment operation, but rather to create a CallSite<T> object (< >p__Site1), as shown below.
Note the above CallSite<T> (called "the dynamic site object" in MSDN) is one of the core components of DLR.
By calling the static method Create() of the CallSite<T> class a dynamic site object is created. During the course, C# compiler will assign a class derived from the CallSiteBinder object (known as "dynamic site bound object") as its argument. Please refer to the following:
Note the dynamic site binding site is related to specific language. For example, IronPython and C# have their own dynamic site binding object.
By digging further, we can discover that the main work of the dynamic site binding object is convert the dynamic expression (in this case d++) to an "Abstract Syntax Ttree (AST)". The syntax tree is called "DLR Tree ", which is created based on the LINQ expression tree introduced in .NET 3.5, therefore, sometimes also known as "Expression Tree".
Internally DLR invokes the Compile() method of the expression tree to generate IL instructions, so that a delegate that can be executed by CLR will be created (in this case the type is Func<CallSite, object, object>).
In addition, the dynamic call site object (in this case, <>p__Site1) has a Target property, which is responsible for referencing the above ready-to-use delegate.
After the delegate is successfully generated, the dynamic expression gets executed in the way of implementing the delegate.
Simplified code can be indicated like the following (via .NET Reflector, for ease of read, the variable names got modified):
Lastly, note that the above type inference, method binding, and the IL code generation related work are all done in the running time.
Is dynamic code slow?
Dynamic programming language is easy to use, with code compact, and flexible programming, but the performance is always its weakness. To improve performance, DLR designs a three-level caching strategy.
The CallSite<T> object is capable to add the corresponding test conditions to the syntax tree for the dynamic expression invocation conversion, and also constitutes a Rule. This rule can be used to determine if a syntax tree can be used for a particular dynamic invocation expression.
For example, consider the following dynamic expression:
If d1 and d2 are both of an integer type at running time, then the rule generated by DLR will be:
By checking the test conditions in the above rule, DLR can judge whether a dynamic expression can use this syntax tree contained in this rule.
Note the Rules are the main objects of DLR caching.
The delegate referenced by the Target property of the previously-introduced dynamic call site object is the first level cache. It implements such processing logic:
If there is not a proper rule even in the level 3 cache, then a new rule will be created automatically. And if the creation fails, the current programming language (e.g. C#) provides the default call to decide how to deal with the case. The usual solution is to throw an exception.
Note that the current version of DLR caches 10 rules in level 2, while in level 3 100 rules.
Owing to DLR's own "rule" caching system and with full use of the CLR provided JIT cache, the dynamic code will result in poor performance only at the first time invocation, but subsequent calls can approximate the performance of the static code.
Integrate C# 4 and Dynamic Languages
Since almost all programming languages can be expressed via the abstract syntax tree, from the viewpoint of theory, interpretabilities between an infinite number of programming languages can be supported by DLR. In the current version, merely interpretabilities between C#/Visual Basic.NET and IronPython/IronRuby can be supported. But we can have enough reason to believe that soon there will appear the DLR implementations of other dynamic programming languages.
Dynamic object communication protocol
To achieve interoperability between different languages is no doubt a problem since the characteristics of various dynamic programming languages are quite different. For this, DLR has taken a clever strategy - it doesn't design a "common type system" (as done in CLR), but design a "universal object communication protocol". According to this protocol, all the dynamic objects that need interoperability must implement the IDynamicMetaObjectProvider interface. This interface defines a GetMetaObject() method which accepts a syntax tree object as a parameter and returns to the outside caller a DynamicMetaObject object.
Note the DynamicMetaObject object exposes to the outside world two important properties: Restrictions and Expression. The property Restrictions can be used to reference a set of test conditions, while property Expression is used to reference a syntax tree. Combination of the two properties forms the Rule for object caching by the CallSite<T> object.
After the dynamic site bound object (CallSiteBinder) obtains the DynamicMetaObject object, DLR calls various methods provided in this object to create "rules", so that the Target attribute of the CallSite<T> object references it to complete the dynamic binding.
The integrated environment for dynamic languages
To facilitate the integration between static dynamic programming languages and various kinds of dynamic programming languages, DLR provides a set of components named "Common Hosting", among which are two important objects - ScriptRuntime and ScriptScope.
Here we take IronPython, for example, to describe how to integrate dynamic programming language related code into C# 4.
First, you need to create a ScriptRuntime object, which is a top-level object, used in a. NET application domain to embed a specific operating environment for some dynamic language:
Then, create a ScriptEngine object, which is the execution engine of the dynamic language code:
Next, use the ScriptScope object (which is similar to the C# namespace) to define some variables that can be passed to the dynamic code data. For instance, the following code will create a C# ExpandoObject object passed to the Python code:
The sample code on the top is a direct implementation of Python code. In the actual development environment, though, the more common case is directly executing Python code in the file.
Assumed there is a Calculator.py file, which defines an Add function like this:
Then, the following C# code can be executed:
This example indicates under the support of DLR, you can make use of the libraries written in dynamic programming language in a static programming language environment. In turn, dynamic programming languages based on the DLR implementation can also use a library written for a static language, such as the standard .NET-based library.
This means two things:
(1) We can now piece "static" and "dynamic" programming languages together to develop a number of highly interactive applications. A very noteworthy field is to use static programming languages to build the system framework while use dynamic programming languages to set up the interactivity.
(2) In the future there will surely be some libraries both suitable to "static" programming languages and to "dynamic" ones, to make a big stride towards the "reuse everywhere" goal.
BTW, Visual Studio 2010 provides special project templates for the .NET programming language F#, but not for IronPython and IronRuby like dynamic languages. However, current news from Internet says in Visual Studio 2012 this situation will get better –fully support the development of dynamic languages.
Summary
In this article, we've mainly focused upon the dynamic feature in C# 4.0. However, some of the related interesting topics have also been covered. From the development road from C# 1.0 to 4.0, we can clearly see its developing path, and hence draw such a conclusion: the future programming languages should be multi-paradigm, with a high degree of composability, and with more common phenomena that in one project there will combine multiple programming languages, as well as use a variety of programming paradigms.
About Xianzhong Zhu
 |
I'm a college teacher and also a freelance developer and writer from WeiFang China, with more than fourteen years of experience in design, and development of various kinds of products and applications on Windows platform. My expertise is in Visual C++/Basic/C#, SQL Server 2000/2005/2008, PHP+MyS...
This author has published 81 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
Html Encoding Nuggets With ASP.NET MVC 2
read more
Dynamic in C# 4.0: Creating Wrappers with DynamicObject
read more
Fun with C# 4.0s dynamic
read more
Fun With Method Missing and C# 4
read more
Dynamic Languages: A Separation of Concerns
read more
Have I Missed The Bus?
read more
DotNetNuke Case Study: DNNTreeView for Large DNN Applications
read more
Image Transforms with the ASP.NET Generated Image Control
read more
Javascript Array Fun
read more
ASP.NET Dynamic Data: Customize a template field
read more
|
|
Please login to rate or to leave a comment.