Chapter 05

値型と参照型

oskgw log
oskgw log
2022.05.05に更新

値型と参照型

型には、最初に把握すべき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
  • 真偽値 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」のとおり、積極的に使うのは避けた方がいいと思っています。