値型と参照型
型には、最初に把握すべき2つの区分があります。
- 値型 ( value type )
- 参照型 ( reference type )
値型
値型は、各変数に個別に中身が割り当たっている状態を想像してください。
言い方としては、インスタンスが含まれているといいます。
プログラムの見た目通りなので、最初はこれを追いかけるように見ていけば安心です。
参照型
参照型の変数はデータの場所を格納しています。
どう理解したらいい?
例えるなら、3人がそれぞれにリンゴの話をしているとします。
そこで以下の質問をしたときに、値型なのか参照型なのか違いがでます。
そのリンゴはどこにありますか?見せてください。
- 値型の場合は、3人が自分のポケットからそれぞれ3個のリンゴを出して見せてくれるでしょう。
- 参照型の場合、3人が特定のテーブルにある1個のリンゴを指さして「あれの事!」というのです。
違いによる影響
もし、リンゴをかじって値を減らしたとき
「なんか知らない間に減ってる!」となるのは・・、そうです、参照型ですね。
使い方
このあたりの差が大きいので、仕様に応じて選択されます。
型 ~公式の定義を手短に把握
型の種類
型(type)には、4種類あります。
名称 | 原文 |
---|---|
値型 | value type |
参照型 | reference type |
型パラメータ | type parameter |
アンセーフ型 | type unsafe |
値型 value type
上位クラスから特徴を継承して、さらに次のように詳細化しています。
-
構造体型 struct type
- ユーザー実装の構造体
- 単純型 simple type
- 数値型 numeric type
- 真偽値 bool
- Null許容型 nullable type
-
列挙型 enum
構造体型 ~ユーザー実装の構造体
実装時に、構造体[struct]で定義した型になります。
値型なのでクラスとは取り扱い方が異なります。
基準としては、16バイト以内の構造で、定数的なあまり変化のないデータなら選択します。
現在では通常ではクラスの方が使われることが多いので利用時はそのデータの特徴を検討してください。
構造体型 ~単純型 simple_type
単純型の中には数値型と真偽値があります。
さらに、数値型には扱いが詳細に分類されています。
- 数値型 numeric type
- 整数型 integral type
- sbyte、byte
- short、ushort
- int、uint
- long、ulong
- char
- 浮動小数点型 floating point type
- float
- double
- デシマル型 decimal
- 整数型 integral type
- 真偽値 bool
整数型 integral type
ビットごとに分けると下記のようになります。
sbyteだけなぜか符号付のsigned でsがあり、他はunsigned で最初にuが付く。
統一できなかったんだろうか、、、
8ビット整数
名称 | 範囲 |
---|---|
sbyte | -128 ~ 127 |
byte | 0 ~ 255 |
16ビット整数
名称 | 範囲 |
---|---|
short | -32768 ~ 32767 |
ushort | 0 ~ 65535 |
32ビット整数
名称 | 範囲 |
---|---|
int | -2147483648 ~ 2147483647 |
uint | 0 ~ 4294967295 |
64ビット整数
名称 | 範囲 |
---|---|
long | -9223372036854775808 ~ 9223372036854775807 |
ulong | 0 ~ 18446744073709551615 |
文字型
名称 | 範囲 |
---|---|
char | 0 ~ 65535 |
ただし、文字型charの値は、Unicode文字セットに対応。
charはと同じ表現を持ち ushort ますが、1つの型で許可されているすべての操作がもう一方の型で許可されているわけではありません。
正直言って、stringの方が使い勝手が良い
ただし、値型の文字という事は覚えておくこと
浮動小数点型 floating point type
2つの浮動小数点型があり下記のビット数(精度)に特徴があります。
名称 | 範囲 |
---|---|
float | 32ビットの単精度 ±1.5 × 10^(-45) ~ ±3.4 × 10^38 |
double | 64ビットの倍精度 ±5.0 × 10^(-324) ~ ±1.7 × 10^308 |
小数で扱う物理データが多いのですが、
if文の判定で、そのまま使わないでください。エラい目に会います。
誤差にふりまわされるので、Errorい目とも云えます
デシマル型 decimal
浮動小数点型では表現できない(表現上の誤差がキツくて使えない)
小数表現をカバーする型です。財務や通貨の計算に適しています。
名称 | 範囲 |
---|---|
decimal | 128ビットのデータ型 1.0 × 10^(-28) ~ 7.9 × 10^28 |
真偽値 bool
ブール値を表していて「true or false」です。
判定結果やフラグに使います。
ちなみにboolの語源は、「George Boole」さん(人名)です。
日本人名なら「真偽 譲二」さんといったところ、、、
構造体型 ~Null許容型 nullable_type
この型は、基になる型をnull値で表すことができます。
なんでわざわざこんな事するのかというと
- データの利用範囲がビット数全部可能性があるとき下記に困ります。
- 初期値:0
この「0」は、データ取得前なのか?それとも取得してから「0」になったのか
見分けがつかないのです。
そのため、未取得の状態をnullに決めることで区別ができたりします。
主にDBからデータを取得したdaoをdtoで読み取るとき
必須項目の数値データを一旦 Null許容型で受け取りDB接続を切る。
C#ロジックにて、取得ミス判定処理を入れたりできます。
列挙型 enum
C#では、様々な型がありますが、ユーザや業務上で特定の型と決めて
その中から選ばれているか判定することで、単にintで判定するより手堅くなります。
- DBアクセスの状態により、排他制御の状態
- エンジン制御時の起動シーケンス
- 保険の契約処理など公的書類などで、和暦(元号表記)
こういった業務上で出てくる特定の状態を示すものに使います。
参照型 reference type
値型と同様に、さらに次のように詳細化しています。
-
クラス型 class type
- ユーザー実装のクラス名
- オブジェクト object
- 動的型 dynamic
- 文字列型 string
-
インターフェイス型 interface type
- ユーザー実装のインターフェイス名
-
配列型 array type
-
デリゲート型 delegate type
- ユーザー実装のインターフェイス名
クラス型 class type
クラス型の表です。値型以降は全て、~の基本クラスです。
クラス型 | 説明 |
---|---|
System.Object | これがすべての始祖です。最終的な基底クラス |
System.String | 文字列型 |
System.ValueType | 値型 |
System.Enum | 列挙型 |
System.Array | 配列型 |
System.Delegate | デリゲート型 |
System.Exception | 例外 |
オブジェクトの型 object
全型の基本クラスで、すべてはobjectクラス型からできています。
動的型 dynamic
プログラムが実行時に決定します。
設計時に想定と構想が定まっているなら静的型付けで十分ですが
モダン言語になるほど動的型付けが強いです。
これは、デバッグしないと不具合が分からなくなる特徴があるので
よくわからないから「dynamic」で実装すると、あとから苦しむので注意して利用します。
文字列型 string
文字列を扱うときは、まずこれを検討して利用します。
型の値は、文字列リテラルを設定できます。
参照型ですが、「==」、「!=」 は、値を比較するように定義されています。
インターフェイス型 interface type
オブジェクト指向で出てくるインターフェイスを実装できます。
仕様を記述する意味合いが大きいです。
配列型 array type
同様の型をインデックスを使ってアクセスするものです。
0個以上の変数を持った構造です。
デリゲート型 delegate type
関数ポインターに相当するものです。
型パラメーター type parameter
通常の関数では、引数に値やクラスなどを持たせるのですが
値型のintでもfloatでも、とにかく加減の演算をしたいとき、
「型に関係なく」計算できるようにしたいとき、そのパラメータを型にした
メソッドを作成できます。
おなじく、「型に関係なく」コレクションしたいときも同様です。
これらを実現しているのが型パラメーターです。
アンセーフ型 type unsafe
C#にはポインタがないのですが、仮想的にポインタを実現しているのがunsafeです。
自由にアクセスしていまうと、何のためのマネージドコードなのか分からなくなります。
この名称「unsafe」のとおり、積極的に使うのは避けた方がいいと思っています。