2016年6月13日月曜日

[C#] Objectタイプ、varタイプ(匿名タイプ)、dynamicタイプ

こんにちは。明月です。
今日は高級データタイプ文法のObjectタイプ、varタイプ(匿名タイプ)、dynamicタイプについて勉強します。


筆者はC#の勉強の初め部分でデータタイプについて勉強したことがあります。


[C#] データタイプとリテラル(literal)、 Nullable


[C#] 変数と定数


すなわち、データを宣言して使うことあるいはクラスを割当して使う方法は「データタイプ 変数名 = new クラス名()」の形で使いました。



上の例を見るとデータタイプに「TestClass1」を宣言してクラスを割り当てて使います。ここまでは今まで勉強したとおりに問題がありません。


Objectタイプ


それでは、C#のことではすべてのデータタイプとクラスの最高の親クラスが存在します。それを「Object」タイプで基本のメソッドは「ToString」等を持っているクラスです。
それですべてのクラス、データタイプは「ToString」を持っていることです。



そうすると次は「Object」タイプの例です。




でもデータタイプを「Object」で宣言して「TestClass1」を割り当てれば、データタイプが一番上位の抽象クラスを宣言したことなので、「TestClass1」タイプままで使われずに、「Object」のタイプに使われるので「TestClass1」の属性を使うことができないですね。それで「TestClass1」属性を使うためには「TestClass1」クラスに強制キャスティングしてから使うことができます。
しかし、強制キャスティングの問題はコンパイルする前の状況でエラーを発見しにくいし、ソース可読性も落ちる問題が発生します。



匿名タイプ(var)


それでデータタイプを正義しなくて使えるタイプがあります。「Object」タイプほどにデータタイプのとしての役割はありませんが、割り当てる時にデータタイプを明示しなくて使うことができる匿名タイプがあります。




でも、匿名タイプは見た目は「Object」タイプと似ていることでみえますが、コンパイル段階でクラスを割り当てる時にデータタイプが決めることなので他のタイプに再割当てはできません。
すなわち、匿名タイプはソース段階の見た目を整理することだけなので性能にも影響がありません。


dynamic


匿名クラスの再割当てる問題を解決するようなタイプが「dynamic」タイプです。匿名タイプはデータタイプをコンパイルする前に決めて使うタイプなら「dynamic」はコンパイルする時にデータタイプを決めるタイプです。



上の例を見ると「dynamic」タイプを使うと「var」と比べて再割当てても変数を使えるし、最後のループ(foreach)部分は「TestClass1」と「TestClass2」は抽象クラスで結んでいることではないが、同じクラスらしくメソッドを呼ばせることができます。


今まで使った部分で「var」と「dynamic」の差を見ると「dynamic」が活用度が高いようで、応用もできそうですね。でも「dynamic」の場合はコンパイル後でデータタイプが決めるタイプで「Reflect」と関係があります。
「Reflect」は次の投稿で勉強しようかと思いますが、簡単に言うとプログラム自体をすべて「static」化して「Invoke」することなので、性能が既存のことより遅くなります。 すなわち、上のループの例みたいに抽象クラスを利用しなくて,メソッド名だけ合わせて使えば大量処理プログラムを作成する時にすごく遅くなります。「Reflect」の説明は後で詳しくしましょう。


改めて纏めると、筆者の場合は「dynamic」タイプはウェブ環境と性能に影響がない場合に使いますが、その以外は使わないほうがよいです。(プログラマ達のスタイルはすべて違うので筆者が言うのが正解ではなく、自分の考えです。)
そして、「var」タイプの場合は勧めないです。確かに「var」タイプはソース作成量を縮めてソース生産性が高くなると思いますが、逆に可読性が落ちるので綺麗が実装ができると思わないです。
でも、「dynamic」は可読性が落ちますが、代わりにソース生産性だけではなく、抽象しなくても抽象クラスを使いらしく作成ができますので、上の条件通りに性能の影響がない場合にはよく使う方です。

0 件のコメント