【C#】「null」と「""」と「0」と「Empty」の結論

f:id:nuakam:20180124180536j:plain:w600

はい。Unityの記事です。

UnityはC#でコーディングするのでUnityの記事といって問題ない。(´・ω・`)

nullと""と0とEmpty

宣言とか初期化するときにいっつも気になる初期化。
でも何となく理解してる分何となく使ってしまっている。

もうこの際はっきりさせとこうジャナイカ(`・ω・´)

基本

まずは初歩的なところから順に

int型
 0 = null
"" = null

↑これは間違い。

ちょっと前にzaifでこの失敗してあわや大惨事になる寸前でした。

int hoge = 0;
int? fuga =  null; //null許容型

intにnull許容型使うぐらいなら説明するまでもないことかもしれない。

  • hoge は"0"という値を持っている。
  • fuga は値を定義していない。

以下のとっても分かりやすい図を見てみよう。
f:id:nuakam:20180404130930p:plain

あくまで単純な例として、四角がメモリ。

hogeは0を持つが、fugaは矢印自体を持っていない。
それがnull。(厳密にはちょっと違う。)

nullはなんか使ってなさそうなメモリを指す。もしそこのメモリが初期化されてなかったら、その値が出てしまう。

Debug.Log("hogeの値=" hoge +"fugaの値=" +fuga);

hogeの値=0 fugaの値=192817863846293472364294343421

zaifはコレをやったっぽい。
0とnullを混同して残金0でお金引き出そうとしたら、無限にお金が湧いてでてぐわぁって。
Youtuberが生放送中にこれを発見した、彼は善良なユーザーだったため運営に連絡。 その後ロールバックして事なきを得た。

string型

これがstringだと""(空文字)になる。

空文字という文字も持つのが ””
定義していないを示すのが null

空文字を何度も宣言するとその度にインスタンスを生成するか

しない。

下のブログがとっても分かりやすい。
blogs.wankuma.com

簡単に言うと空文字という値を、全初期化済の変数が参照している(と認識した)。
つまりメモリ領域ではひとつ分の空文字しか保持していない。

string.Empty はダメ

C#だと初期化に

string fuu = "":
string bar = string.Empty;

の2つパターンがあり、ちょくちょく論争が起こる。


先に結論を言うと ””(空文字)だけで統一するべし。


これもさっきと同じブログがとっても分かりやすい。
blogs.wankuma.com

String.Empty は文字列ではなく「フィールド」なのである。フィールドであるため、String.Empty をロードして参照を辿っていかなければならない。"" の方は単純にメタデータのリテラル文字を突っ込んで終わり。どちらの方が速いのか、公式の資料がないので(あるかもしれないけど知らない)正確には分からないが、後者の方が断然速いはず。(※1)。

※1 コンパイル時や JIT 時に最適化されたら話は変わる。


まあ今のパソコンやらスマホなら微々たる差だけど。(´・ω・`)
大規模コードだったら塵も積もれば山となる的に重くなるかもしれない。

最低限どちらか一方に統一したほうがいい。

Empyと空文字はアプローチが違うため、両方存在すると2つ参照先が作られてしまう。


あんまりいないかもしれないけど、C系統でデバイス作成する時はけっこう気にしなくてはいけない。