C#の基礎 C/C++とC#の違い

私はUnityでC#を使っているのですが、ほとんどC++と同じ感覚で扱っています。もちろんほとんど問題なく動くのですが、ネットのSourceCodeを読んだりしているとちらほらわからないものがあります。また、メモリの管理が違うので学ばないで使っていると怖い部分もあります。やはりそこまでわかるプロフェッショナルでありたいですね!

C++を学んだ私がC#を学んで新しく覚えたことをメモします

  • C#の組み込み型 C#の組み込み型(int型など)のサイズは処理系に依存せずに定まっています。C#では組み込み型に.NET型という別名のものがあります。例えばint型には別名System.Int32、float型にはSystem.Singleとう別名があります。さらに、C#では組み込み型が構造体でメソッドが定義されています。例としてint.MaxValue で変数の最大値が使えり、int.Parse(string型の変数) でstring型からint型に変換できたりします。変数名.GetType()で変数の型を取得できたり、変数名.ToString()で簡単にstring型を取得できるのも便利ですね。
  • structとclass 構造体は値型なのに対し、classは参照型です。同じように使ってはいけません。メモリに確保&解放され方が全く違います。C++と同じで構造体は継承できません。これらの仕様から向き不向き(構造体は多態性が使えない、大きいデータのコピーが苦手など)があり、使い方によっては実行速度に差が生じます。
    C++ではnewすればヒープ領域(スタック上のポインタをまたぎますが、広く扱える領域)newを使わなければスタック領域(Scoopが明確で高速)ですが、C#ではすべてnewすることにより格納する領域を確保します。格納する領域は型によって決められます。基本方&構造体はスタック領域、classや配列はヒープ領域。※ヒープ領域がガベージコレクションで自動管理される領域で、もしUnityでいうUpdate()のような毎フレーム呼ばれているところでclassや配列をnewしようものなら頻繁にガベージコレクションを呼ぶ原因になるのでやめましょう。

許可されているリンクを貼っておきます。

クラスと構造体の使い分け: .NET Tips: C#, VB.NET

 連載 改訂版 C#入門:第5章 C#のデータ型 (3/4) - @IT

 

メモリ管理 - コンピュータの基礎知識 | ++C++; // 未確認飛行 C

.NETにおけるマネージヒープとガベージコレクション - Qiita

 

  • virtual C++ではvirtualを使えば派生先のメソッドが自動的に呼ばれますね。
    C#では基底クラスが呼ばれてしまいます。同じように動かす手目には派生先の同名メソッドにoverrideと付け足せばC++と同じ挙動になります。

virtualとoverrideによるメソッドの上書き - (void*)Pないと

 

  • decimal型 double型より精度の高い128ビット、少数点下28桁まで正確な計算ができるのだそう。私は使ってない...
  • castはちゃんと明示的に! enum型をint型のように使うとコンパイラ通りませんでした。しっかり (int)enumの○○型 とキャストしてあげましょう。
  • switch文でフォールスルーができない! switch文でたまにbreakしないで一つしたのcase文の処理もやりたいときあると思いますが、C#ではそういったフォールスル―が禁止です。
  • switch文の式でint型だけでなくstring型が使える。

switch(string型){

    case"a": //何もしない場合break文はいらない。複数のラベル扱いになる。

    case "b":

    Console.WriteLine("b");//命令があると次のcase文に入るフォールスル―ができない。

    //break文がないのでエラーがでる!

    case "c": 

    Console.WriteLine("c");

    break; //このラベルは命令があるので必要

 default:

}

 

  • object型 いろんな型の値を動的に入れることができる。object型は参照型です。データ自体はヒープに保存していて、その参照をobject型の変数に格納しています。どんな型も暗黙的に代入できます。(box化といいます) 私は使ってない...

int iNum = 100;

object obj;

obj = iNum.ToString();  //ボックス化
string str = obj as string; //ボックス化解除

  • is hoge is int で、hogeがint型かどうかtrue,かfalseを返してくれます。
  • as  castに近いですが、castは変換に失敗した場合例外をなげるのに対し、asはnullを返します。例外を投げないasはcastより高速みたいですね。 また、asはキャストと違って参照型への変換しかできませんhoge as int はできません。ユーザー定義したキャスト変換も呼べないので、継承したクラスなど限定的に使えます。(ただし上記の通り高速でかなり重宝します)

詳しくはリンクを許可しているページを貼っておきます。

.NET TIPS:as演算子とキャストの違いは? - @IT

 

  • ref&out C++では関数に値型を渡すと変更されず、参照やポインタを渡すと元のデータの値も変更されますね。C#では違います。値型でもrefかoutを宣言して使うと変更されるようになります。結構ややこしい。refとoutの違いはrefが初期値が代入されていないといけません。outは初期値はいりませんが関数内で代入が必須です。

 

  • foreach for分の方が高速ですが、連想配列を回すのにとても便利な機能。何回目のLoopかインデックスも取得可能です。連想配列(Dictionary, MapやHash, Tableとも言う)を使ってなかった人は一緒に覚えるといいと思います。

 

  • 連想配列(Dictionary) C#使うならListと並び定番のコンテナ。C++でいうstd::map(これは2分木探索)私はコンテナクラスの挙動の勉強中なので詳しくは書けません。内部実装がどうなっているのかは注意して使いたいですね。

 

  • 機能が強力 例えばRijndael(ラインダール)クラス使えば暗号&複合化がすぐにできてしまう。他にもXMLを読み込んでそのままオブジェクトとして扱えたり、凄く便利。