佐々木屋

技術的なことから趣味まで色々書きます

null許容型(C#とVB.NETの違い)

参照型はnullを許容していますが、値型はどうでしょうか。実はここでもC#VB.NETで微妙に挙動が異なります。

C#におけるnull代入時の挙動

参照型はnullを許容していますが、値型はnull非許容です。つまり、以下のような構文はそもそもコンパイルエラーとなってしまいます。

int a = null;
decimal b = null;


VB.NETにおけるNothing代入時の挙動

VB.NETのnullはNothingとなります。参照型はC#同様null許容なので何の問題もありませんが、問題は値型です。結論から言えば、C#であろうとVB.NETであろうと値型はnull非許容です。

Dim a As Integer = Nothing
Dim b As Decimal = Nothing

しかしコンパイルが通ってしまいます。何故でしょうか。

VB.NETは暗黙的に初期化されてしまう

以下の構文をそのまま実行してみましょう。

Dim a As Integer = Nothing
Dim b As Decimal = Nothing
Console.WriteLine(a)
Console.WriteLine(b)
0
0

つまり、VB.NETの場合null非許容の値型へNothingを代入すると、内部的に初期化される仕様となります。

VB.NETの値型がnull非許容ということは、以下の構文を書くとよく分かります。

Dim a As Integer = Nothing
If a Is Nothing Then
End If

これは2行目でnull許容に関するコンパイルエラーとなります。

'Is' 演算子は型 'Integer' のオペランドを受け付けません。オペランドは参照型または Null 許容型でなければなりません。




このように、C#VB.NETで挙動が違い、またVB.NETの場合は非常に分かりにくい仕様になっています。

これの何が問題かというと、オブジェクト指向でデータベースを扱ったりクラスを設計した場合、どうしてもnull(要は何もない状態)を返したい場合が出てきます。C#であれば値型はnull非許容なので明示的にnull許容型(別途説明します)にすれば何の問題もありませんが、VB.NETの場合、例えばInteger型だとNothingを代入しても0が返ってきてしまいます。つまり、Nothing代入による初期値0のことなのか、処理結果の0なのかの判断が出来ないということになります。