【C#】「null」と「""」と「0」と「Empty」の結論
はい。Unityの記事です。
UnityはC#でコーディングするのでUnityの記事といって問題ない。(´・ω・`)
nullと""と0とEmpty
宣言とか初期化するときにいっつも気になる初期化。
でも何となく理解してる分何となく使ってしまっている。
もうこの際はっきりさせとこうジャナイカ(`・ω・´)
基本
まずは初歩的なところから順に
int型
0 = null
"" = null
↑これは間違い。
ちょっと前にzaifでこの失敗してあわや大惨事になる寸前でした。
int hoge = 0; int? fuga = null; //null許容型
intにnull許容型使うぐらいなら説明するまでもないことかもしれない。
- hoge は"0"という値を持っている。
- fuga は値を定義していない。
以下のとっても分かりやすい図を見てみよう。
あくまで単純な例として、四角がメモリ。
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系統でデバイス作成する時はけっこう気にしなくてはいけない。