StaDynは、 .NETプラットフォーム向けのオブジェクト指向汎用プログラミング言語であり、同一のプログラミング言語内で静的型付けと動的型付けの両方をサポートしています。
StaDyn コンパイラは、動的に型付けされたコードの型情報を収集します。この型情報は、コンパイル時に型エラーを検出し、大幅な最適化を実行するために使用されます。そのために、型再構築 (推論)、フローセンシティブ型、共用体と交差型、制約ベースの型付け、エイリアス分析、メソッド特殊化を提供します。その最初のプロトタイプは、C# 3.0 の修正として 2007 年に登場しました。型推論は、初期化されたローカル変数を定義することvarしか提供しない C# とは異なり、新しい型として含めることによってサポートされましたvar。参照のフローセンシティブ型はvarコンパイラによって推論され、型安全なダックタイピングが提供されます。[ 4 ]プログラマがより寛容なアプローチを必要とする場合、dynamicの代わりに型を使用できますvar。型推論は依然として実行されますが、dynamic参照は動的言語の参照により近い動作をします。
StaDynは、オビエド大学のFrancisco Ortin [ 1 ]によって設計されました。この言語は、Francisco Ortinのほか、Miguel Garcia、Jose Baltasar García Perez-Schofield、Jose Quirogaを含む、Computational Reflection研究グループ[ 2 ]のさまざまなメンバーによって実装されました。
StaDynという名前は、static(静的)とdynamic(動的)を組み合わせた造語で、静的型付けと動的型付けの両方の利点を提供することを目指していることを示しています。
動的言語と同様に、変数は同じスコープ内で異なる型を保持することができます。
using System ; class Program { public static void Main ( ) { Console.Write ( " Number: " ) ; var age = Console.In.ReadLine ( ) ; Console.WriteLine ( " Digits : " + age.Length ) ;age = Convert.ToInt32 ( age ) ; age ++ ;Console.WriteLine ( "誕生日おめでとう、あなたは今" + age + "歳になりました。" ) ; int length = age.Length ; // * コンパイラエラー} }変数ageは最初に文字列として推論されるため、そのプロパティを取得しても安全ですLength。次に、整数を保持するため、age++有効な式となります。コンパイラは最後の行でエラーを検出します。なぜなら、Lengthはもはやによって提供されていないからですage。
生成されたコードでは、年齢を表すのに単一の変数ではなく、文字列型と整数型の 2 つの異なる変数を使用します。これは、 SSA フォームをObject計算するアルゴリズムの変更によって実現されます。[ 5 ]これにより、実行時の型変換が不要になるため、生成されたコードの効率が向上します。
varまた、dynamic変数にはフローに敏感な型を保持できます。
using System ; class Program { public static void Main ( String [] args ) { var exception ; if ( args.Length > 0 ) exception = new ApplicationException ( "アプリケーション例外です。" ) ; else exception = new SystemException ( "システム例外です。" ) ; Console.WriteLine ( exception.Message ) ; } }と の両方がそのプロパティを提供しているため、Messageからプロパティを取得するのは安全です。そうでない場合は、コンパイラエラーが表示されます。このようにして、StaDyn は型安全な静的ダックタイピングシステムを提供します。exceptionApplicationExceptionSystemException
次のプログラムでは:
using System ; class Program { public static void Main ( String [] args ) { var exception ; switch ( args.Length ) { case 0 : exception = new ApplicationException ( "アプリケーション例外です。" ) ; break ; case 1 : exception = new SystemException ( "システム例外です。" ); break ; default : exception = "これは例外ではありません。" ; break ; } Console.WriteLine ( exception.Message ) ; // * var ではコンパイラエラーが発生しますが、dynamic では発生しませんConsole.WriteLine ( exception.Unknown ) ; // *コンパイラエラー} }プロパティMessageは によって提供されていないStringため、 に対してコンパイラ エラーが表示されます。ただし、を としてexception.Message宣言すると、前のプログラムはコンパイラによって受け入れられます。は よりも寛容で、動的言語の慣習に従っています。ただし、静的型チェックは依然として実行されます。これは、 が として宣言されていてもコンパイラが に対してエラーを表示するコードの最後の行に示されています。これは、可能な 3 つの型 ( 、および)のいずれもメッセージをサポートしていないためです。[ 6 ]exceptiondynamicdynamicvarexception.UnknownexceptiondynamicApplicationExceptionSystemExceptionStringUnknown
dynamic型チェックをより安全またはより寛容にするためにvar型を明示的に使用することもできますが、単一var参照の動的な動作は、コマンドラインオプション、XML 構成ファイル、および Visual Studio のプラグインによって変更することもできます。[ 7 ]
varまた、dynamic型はオブジェクトフィールドとして使用できます。
class Wrapper { private var attribute ;public Wrapper ( var attribute ) { this.attribute = attribute ; }public var get () { return attribute ; }public void set ( var attribute ) { this.attribute = attribute ; } }class Test { public static void Main () { string aString ; int aInt ; Wrapper wrapper = new Wrapper ( "Hello" ); aString = wrapper . get (); aInt = wrapper . get (); // * コンパイラエラーwrapper.set ( 3 ); aString = wrapper.get ( ) ; // *コンパイラエラーaInt = wrapper.get ( ) ; } }このWrapperクラスは任意の型をラップできます。メソッドを呼び出すたびにset、 の型がattribute引数の型として推論されます。各オブジェクトは の型が異なる可能性があるattributeため、その型はクラス全体ではなく、インスタンスごとに格納されます。このようにして、上記のコードに示されている 2 行はコンパイル エラーを報告します。この動作をサポートするために、型ベースのエイリアス解析アルゴリズムが実装されています。[ 8 ]
次の方法を分析してみましょう。
public static var upper ( varパラメータ) {パラメータを返します。ToUpper (); }の型parameterと関数の戻り値はコンパイラによって推論されます。そのために、upperメソッドの型に制約が追加されます。引数はToUpperパラメータのないメソッドを提供する必要があります。呼び出しごとに制約がチェックされます。さらに、の戻り値の型は、引数によって実装される対応するメソッドupperの戻り値の型として推論されます。 [ 9 ]ToUpper
プログラマは、を宣言する際にvarまたはのいずれかを使用することで、メソッド呼び出し時の型チェックの方法を変更できます。 に渡される引数がフローセンシティブ型 (上記のコードの 、 または 変数など) を保持していると仮定します。 の場合、引数のすべての可能な型が を提供する必要があります。の場合、少なくとも 1 つの型が を提供する必要があります。dynamicparameterupperApplicationExceptionSystemExceptionStringexceptionvarToUpperdynamicToUpper
StaDyn によって収集された型情報は、生成されたコードで大幅な最適化を実行するために使用されます。[ 10 ]型検査と型キャストの回数が削減され、リフレクションが回避され、頻繁に使用される型がキャッシュされ、制約付きメソッドが特殊化されます。すべての最適化の目的は、実行時に実行される型チェック操作の数を減らすことです。これは、ほとんどの動的言語の主なパフォーマンス低下要因です。これらの型チェックの多くは、StaDyn コンパイラによってより早い段階で実行されます。StaDyn の実行時パフォーマンスの詳細な評価については、[ 4 ]に詳述されています。