2010年になった事なので、C# 4.0の追加機能を少しメモしようと思います。
現在Beta版が提供されているVisualStudio2010ですが、Visual C#も当然バージョンが
あがっています。次のバージョンはC# 4.0です。
今回は、そのC# 4.0の追加機能をちょこちょこメモしていきます。
ネタ元としているのは、以下のページ
- Visual C# 2010 のリソース
からダウンロードできる。C# 4.0ホワイトペーパー (January 10)です。
C# 4.0の主要テーマは
動的プログラミング (Dynamic Programming)
となっています。なので、今回の追加機能もそれに関連する機能が追加されています。
大項目は以下の4つです。
- Dynamic lookup
- オブジェクトを動的に扱う機能
- Named And Optional parameters
- VBと同じレベルの名前付き引数とオプショナル引数
- COM interop features
- C#にて、COMを扱いやすくする機能 (Dynamic lookupとNamed And Optional parameters)
- Variance
- 共変性/反変性ともいいます。ジェネリックに対する追加機能です。
今回は、Dynamic lookupについてです。
C# 4.0で、以下のキーワード(型)が追加されました。
dynamic
文字通り動的なオブジェクトを表すものです。
以下のようにすると
dynamic dynObj = GetDynamicObject();
変数dynObjは動的なオブジェクトとして扱われ、コンパイル時の型チェックが
行われません。実際に型の解決が発生するのはランタイム時になります。
C# 3.0で追加されたvarと似ていますが、こちらはあくまで型の推論です。
なので、型のチェックがされますが、dynamicの方はコンパイル時のチェックが
行われません。
また、varとは違い、dynamicは引数の型や戻り値の型としても利用できます。
public dynamic GetDynamicObject(dynamic paramter) {
....
}
なんていうメソッドも定義可能です。
また、ジェネリックの型引数としてももちろん利用できます。
List<dynamic> dynList = new List<dynamic>();
内部的には、dynamicとして定義された値はコンパイル時に
object型に変換されます。なので、実行時にdynamic型というのは
存在しません。
dynamicが追加されたことにより以下の点が行えるようになりました。
- 遅延バインディング (late binding)
- ダックタイピング (duck typing)
late bindingはいいとして、pythonやrubyなどでよく言われる
duck typingが出来るようになるのは面白いですね。
duck typingとは、ざっくりと書くと以下のような事です。
どんなインターフェースや親クラスを実装/継承しているのかに関係無く 特定の機能(メソッドやプロパティなど)を持っているものはみんな同じ ものとして扱う。 (アヒルかどうかは分からないけど、アヒルのような鳴き声をしていたり アヒルのような歩き方をしている場合、アヒルとして扱う)
以下のような感じです。
class A { public void Execute() { ... } } class B { public void Execute() { ... } } // // クラスAとBはそれぞれ、親クラスも共有しておらず、特定のインターフェースも // 実装していない。でも、Executeという名前のメソッドは持っている。 // なら同じ仲間のものとして扱う. // new List<dynamic>{ new A(), new B() }.ForEach(dynObj => dynObj.Execute() );
実際、実務レベルでdynamicを多用するかというと、多分あまり使われないだろうな
というのが個人的な感想です。ただ、COM Interopでは大活躍で、今までC#では
面倒だった部分が大分書きやすくなります。
どんな風になるのかは、下記のサンプルを参照お願いします。
以下、サンプルです。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Excel = Microsoft.Office.Interop.Excel; namespace DynamicLookup01 { class Program { static void Main(string[] args) { (new Program()).Execute(); } private void Execute() { // // dynamicのサンプル. // // dynamicを利用すると、文字通りオブジェクトを動的に扱う事が // 出来るようになる。 // // 変数として利用するだけではなく、戻り値や引数の型としても利用できる。 // // C# 3.0で追加されたvarとの違いに注意。 // varは、あくまでも型の推論であり、コンパイル時に問題は解決される。 // // varとは異なり、dynamicを利用する場合、コンパイル時に型の問題は // 無視され、ランタイム時に解決が行われる。 // (つまり、間違ったメソッド名を指定している場合は実行時にエラーが発生することになる。) // (内部的には、コンパイル時にobject型とCallSiteに変換される模様。なので実行時にdynamic型というのは存在しない。) // // dynamicが効果を発揮するのは、COMを利用する処理やPythonなどの動的言語とやり取りを行う場合 // または、リフレクションなど、コンパイル時に型がはっきりしない場合に有効となる。 // // 以下の例では、サンプルとしてOperationクラスを作成し、それをFactoryクラス経由でdynamic型、object型, Operation型として // 取得するようにしている。呼び元(Program.Execute)では、dynamicで受け取り、動的にメソッドをコール // している。 // dynamic operation1 = OperationFactory.GetOperationAsDynamic(); dynamic operation2 = OperationFactory.GetOperationAsObject(); dynamic operation3 = OperationFactory.GetOperation(); new List<dynamic>{ operation1, operation2, operation3 }.ForEach(dynObj => dynObj.PrintHelloWorld()); // // dynamic型を引数として公開しているメソッドを呼んでみる. // operation1.PrintStrings("HELLO DYNAMIC WORLD"); (new Operation()).PrintStrings("HELLO DYNAMIC WORLD"); // // COMの呼び出し. // // Excel操作を行っている。PIAにもdynamicが設定されており // 以下の例でいうと、Excel.WorkBook.Addメソッドの戻り値はdynamicとなっている。 // // これにより、今までは // ((Excel.Range) workSheet.Cells[1, 1]).Value = "HELLO DYNAMIC WORLD"; // のようにしなければいけなかった部分が // workSheet.Cells[1, 1].Value = "HELLO DYNAMIC WORLD"; // と記述できるようになる。 // // また、Excel操作中に呼び出している各メソッドにてType.Missingが見あたらないのは // C# 4.0から追加されたオプショナル引数と名前付き引数のおかげである。 // Excel.Application app = new Excel.Application(); app.Visible = true; Excel.Workbook workBook = app.Workbooks.Add(); dynamic workSheet = workBook.Sheets.Add(); workSheet.Cells[1, 1].Value = "HELLO DYNAMIC WORLD"; Console.WriteLine("起動されたExcelを確認すると文字列が挿入されています。キーを押下すると処理を進めます。"); Console.ReadLine(); app.Quit(); // // 上記の処理と同じ内容をExcel.Application経由で行う. // var excel = new Excel.Application(); excel.Visible = true; excel.Workbooks.Add(); excel.Cells[1, 1].Value = "HELLO DYNAMIC WORLD"; Console.WriteLine("起動されたExcelを確認すると文字列が挿入されています。キーを押下すると処理を進めます。"); Console.ReadLine(); excel.Quit(); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } #region Sample Classes class OperationFactory { public static dynamic GetOperationAsDynamic() { return new Operation(); } public static object GetOperationAsObject() { return new Operation(); } public static Operation GetOperation() { return new Operation(); } } class Operation { public void PrintHelloWorld() { Console.WriteLine("Hello World"); } public void PrintStrings(dynamic strings) { Console.WriteLine(strings); } } #endregion } }