C#4.0の新機能。 パート1:ダイナミック

PDCで導入されたC#4.0言語の最も興味深い機能の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 .



  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 .



これで、通常どおりメソッドを呼び出すことができます。




  1. var test = new TestClass();
  2. test.TestMethod1();
  3. test.TestMethod2();
*このソースコードは、 ソースコードハイライターで強調表示されました。
予想どおり、すべてが完全にコンパイルされました。 次に、新しい動的キーワードを使用します




  1. 動的テスト= 新しい TestClass();
  2. test.TestMethod1();
  3. test.TestMethod2();
*このソースコードは、 ソースコードハイライターで強調表示されました。
何も変わっていませんか? まったくありません。 すべてが以前とまったく同じ方法でコンパイルされますが、メソッド呼び出しはコンパイルではなく実行時にバインドされます。 つまり、次のように記述した場合:




  1. 動的テスト= 新しい TestClass();
  2. test.TestMethod1();
  3. test.TestMethod2();
  4. test.TestMethod3();
*このソースコードは、 ソースコードハイライターで強調表示されました。
とにかくコードは正常にコンパイルされますが、起動後にこの例外が発生します。

ここで何が起こったのですか? Reflectorが語ったことは次のとおりです。




  1. private static void Main( string [] args)
  2. {
  3. オブジェクト 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.RuntimeBinder.GetInstance()、 falsefalse"TestMethod1"typeofobject )、 null ));
  7. }
  8. <Main> o__SiteContainer0。<> P__Site1.Target(<Main> o__SiteContainer0。<> P__Site1、テスト);
  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.RuntimeBinder.Gettime()、 falsefalse"TestMethod2"typeofobject )、 null ));
  12. }
  13. <Main> o__SiteContainer0。<> P__Site2.Target(<Main> o__SiteContainer0。<> P__Site2、テスト);
  14. }
*このソースコードは、 ソースコードハイライターで強調表示されました。
まず、コンパイラはo__SiteContainer0フィールドを生成して、呼び出しの場所に関する情報を保存しました。 オブジェクトを含む変数testを見ると、その型が型オブジェクトになっていることがわかります 。 したがって、実際には、これは動的な型ではなく、コンパイラ側のアシスタントにすぎません。呼び出しているメソッドに関するすべての情報。 呼び出しの場所が示されるとすぐに、変数testで呼び出されます。 ご覧のとおり、コンパイラがすべてを行ってくれました。



この例では、私たちがやっていることはまったく価値がないように見えますが、コンパイル段階でメソッドがわからない型を使用すると、この機能の威力が発揮されます。 これは、生成されたクラスの場合は動的言語(IronRubyなど)から、またはReflectionを使用する対象からのものである可能性があります。



注釈:記事C#4.0 New Features Part 1.1-dynamic keyword second lookで、著者が新しいテストを実施し、著しく良い結果を示したため、パフォーマンステストに関する部分を翻訳から除外することにしました。



記事翻訳 C#4.0新機能パート1-動的キーワード



私の ブログ からのクロスポスト






All Articles