VBでDateTime型にNothingがセットできる理由
DateTimeは値型である。本来はnull/Nothingはセットできないと思っていた。
でも、VBの場合Nothingがセットできてしまう。デフォルト値はNothingを示す。
なんでだろう?
下の書き込みに答えが載っていた。
GotDotNet Japan 掲示板 スレッド: DateTime型の引数をOptionalにする際の初期値
(Lady.BUGさんの書き込みより)
> DateTime型のデフォルト値は、 = Nohting みたいです。
これはちょっと違いますね、CType(Nothing, 構造体) が未初期化の構造体を返すためです。
.NET では確保されたインスタンスメンバは 0/False/Nothing で初期化されているため、 CType(Nothing, DateTime) が New DateTime(0) と同じ結果にみえているから、と。
NothingをDateTime型と比較しようとすると、CType(Nothing, DateTime)が実行され、未初期化の構造体を返す。未初期化の構造体の中身はNew DateTime(0)である。
これが内部で行われているため、デフォルト値がNothingと等しくなるってことかな?
検証になるかわからないけど、色々初期化方法を試してみた。全て同じ結果を示す。
また、オブジェクトも全て等しいようだ。
Module DateInitializeTest Sub Main() Dim d1 As DateTime = New DateTime(0) Dim d2 As DateTime = Nothing Dim d3 As DateTime = CType(Nothing, DateTime) Dim d4 As DateTime Console.WriteLine("d1 = " + d1.ToString()) Console.WriteLine("d2 = " + d2.ToString()) Console.WriteLine("d3 = " + d3.ToString()) Console.WriteLine("d4 = " + d4.ToString()) Console.WriteLine("d1 = d2? " + d1.Equals(d2).ToString()) Console.WriteLine("d1 = d3? " + d1.Equals(d3).ToString()) Console.WriteLine("d2 = d3? " + d2.Equals(d3).ToString()) Console.WriteLine("d1 = d4? " + d1.Equals(d4).ToString()) Console.WriteLine("d4 = Nothing? " + d4.Equals(Nothing).ToString()) Console.ReadLine() End Sub End Module
結果 d1 = 0001/01/01 0:00:00 d2 = 0001/01/01 0:00:00 d3 = 0001/01/01 0:00:00 d4 = 0001/01/01 0:00:00 d1 = d2? True d1 = d3? True d2 = d3? True d1 = d4? True d4 = Nothing? True
だから値型でもNothingがセットできるのね。
ちなみにC#だとnullで初期化はできないし、DateTime型への変換もできない。
using System; namespace DateTimeInitializeCS { class DateTimeInitializeTest { static void Main(string[] args) { DateTime d1 = new DateTime(0); DateTime d2 = DateTime.Parse("0001/01/01"); Console.WriteLine("d1 = " + d1.ToString()); Console.WriteLine("d2 = " + d2.ToString()); Console.WriteLine("d1 = d2? " + d1.Equals(d2).ToString()); Console.ReadLine(); } } }
以上、C#の場合の初期化方法。
DateTime d3 = null;
とかやるとものすごい勢いで怒られます。
こういうのを意識させないVBは、すごいんだか、怖いんだか・・・