C#[9]

2018/08/18

C#

unsafe

CLR(共通言語ランタイム:Common Language Runtime)によって管理されないコードのことをunsafeと呼ぶ。
その一つがポインター。ポインターは参照型のポインターを取ることはできない。

int *ip; //型* 変数名;
int num = 10;
ip = # //numがint以外の型だったとしても警告は出さない。

&は変数が指す参照(変数の箱の位置)を返す。*は箱の中身(値)を返す。

ポインターは構造体にも使える。構造体のメンバーにアクセスする方法として、アロー演算子が用意されている。

struct MyStruct {
    public int x;
    public int y;
    public int sum() { return x + y; }
}

MyStruct o = new MyStruct();
MyStruct* p;

p = &o;
p->x = 10;
p->y = 20;
Console.WriteLine("Sum is {0}", p->sum());

ポインター変数に算術演算を行うことが可能。ポインターアドレスをインクリメントすると、ポインターが指すメモリ領域の隣のポインター型のアドレスを指すようになります。

  1. int(0)<- Pointer | double(1) | int(2)
  2. インクリメント
  3. int(0) | double(1) | int(2) <- Pointer

デクリメントを行うと逆の現象が起こる。
ポインター変数同士の引き算も可能。この場合、2つのポインター変数のアドレスに囲まれた部分のメモリ領域のデータ個数を返す。ポインター変数同士の足し算はできない。

unsafeキーワード

ポインターを使用するコードはunsafeキーワードを使用する必要がある。unsafeキーワードは文単位でもメソッド単位でも使用できる。

//Mainメソッドの中ではポインターが使用できる。
unsafe static void Main() {

}

unsafeを含むコードが存在する場合コンパイル時にunsafeオプションを用いる必要がある。


## fixed

fixedの使用方法は2つ存在する。
1. ポインターが参照しているオブジェクトがGCの作用によって、移動することをさける。

```C#
ficxed(int* p = &o.num) {
    //oは移動されない。
}
  1. 構造体に固定サイズの一次元配列を作成する場合

通常構造体のメンバを定義した場合、配列の参照が埋め込まれるが、fixedを利用することで配列全体を構造体に含めることができる。
構造体のサイズが重要な意味を持つ状況化などで有用。たとえば、C#で作成したデータ構造にC#以外の言語でアクセスする場合など。
fixedもunsafeコード中で使用することができる。

fixed int BufferedArray[10]

オブジェクト思考できていますか?

「プリミティブ型を全てラップする。」というのはオブジェクト思考っぽいけど、若干やりすぎなような気もしてしまう。「Getter/Setterを使用しない」を意識して開発をしたことがなかったので、一度意識してみようと思う。