📜 ⬆️ ⬇️

New features in C # 4.0. Part 1: dynamic

One of the most interesting features of the C # 4.0 language that was introduced at the PDC is the new keyword - dynamic. It allows the developer to declare an object, the binding to methods of which will be carried out at the stage of execution, not compilation. It is noteworthy that the class that instantiates this object is declared in the standard way.
public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  1. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  2. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  3. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  4. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  5. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  6. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  7. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  8. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  9. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  10. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
  11. public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
public class TestClass { public void TestMethod1() { Console .WriteLine( "test method 1" ); } public void TestMethod2() { Console .WriteLine( "test method 2" ); } } * This source code was highlighted with Source Code Highlighter .
Now we can call its methods as usual:
  1. var test = new TestClass ();
  2. test.TestMethod1 ();
  3. test.TestMethod2 ();
* This source code was highlighted with Source Code Highlighter .
As we expected, everything compiled perfectly. Now use the new dynamic keyword :
  1. dynamic test = new TestClass ();
  2. test.TestMethod1 ();
  3. test.TestMethod2 ();
* This source code was highlighted with Source Code Highlighter .
Nothing changed? By no means. Everything is compiled the same way as before, but now the method calls will be bound at run time, not compilation. Ie, if we write this:
  1. dynamic test = new TestClass ();
  2. test.TestMethod1 ();
  3. test.TestMethod2 ();
  4. test.TestMethod3 ();
* This source code was highlighted with Source Code Highlighter .
The code will compile anyway, but after launch we will get this exception:
What happened here? Here is what Reflector prompted us:
  1. private static void Main ( string [] args)
  2. {
  3. object test = new TestClass ();
  4. if (<Main> o__SiteContainer0. <> p__Site1 == null )
  5. {
  6. <Main> o__SiteContainer0. <> P__Site1 = CallSite <Action <CallSite, object >>. Create ( new CSharpCallPayload (Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance (), false , false , "TestMethod1" , typeof ( object ), null ))
  7. }
  8. <Main> o__SiteContainer0. <> P__Site1.Target (<Main> o__SiteContainer0. <> P__Site1, test);
  9. if (<Main> o__SiteContainer0. <> p__Site2 == null )
  10. {
  11. <Main> o__SiteContainer0. <> P__Site2 = CallSite <Action <CallSite, object >>. Create ( new CSharpCallPayload (Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance (), false , false , "TestMethod2" , typeof ( object ), null ))
  12. }
  13. <Main> o__SiteContainer0. <> P__Site2.Target (<Main> o__SiteContainer0. <> P__Site2, test);
  14. }
* This source code was highlighted with Source Code Highlighter .
First, the compiler generated the o__SiteContainer0 field to store information about the place of the call. If you look at the test variable that contains our object, you will see that its type has become the type object . So, in reality, this is not a dynamic type, but only an assistant from the compiler. Next comes the check of call sites ( callsite) to null and if they are equal to it, then CallSite.Create is used, to which the CSharpCallPayload object is sent , which contains all the information about the method we call. As soon as the place of the call is specified, it is simply called on our test variable. As you can see, the compiler did everything for us.

In this example, what we do seems damn useless, but the power of this feature is manifested when we use a type whose methods we do not know at the compilation stage. This can come from dynamic languages ​​(for example IronRuby), if it is a generated class, or anything else for which we use Reflection.

Remark: I made a decision to exclude the part about performance testing from translation, as in the article C # 4.0 New Features Part 1.1 - dynamic keyword second look the author conducted a new testing and it showed noticeably better results.
')
Translation of article C # 4.0 New Features Part 1 - dynamic keyword

Crosspost from my blog

Source: https://habr.com/ru/post/43773/


All Articles