Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8899

.NETのnull許容値型(Nullable)でハマったこと

$
0
0

データベースの型クラスを自動生成する過程でハマったのでメモ。

現象

  • 実行時にint?(Nullable<int>)となっている変数に対して、型情報を取得するとintが返ってくる

原因

Nullable<T>型がボックス化されるとき、

  • HasValuefalseならばnull
  • HasValuetrueならばT型に

自動でボックス化される。
そのため実行時の型を調べようとobject.GetType()を呼ぶと、T型が返ってくるか、nullにボックス化されるため、NullReferenceExceptionの例外が発生する。

対象の型がNullableかどうか検証するには、Nullable.GetUnderlyingTypeを使うこと。

検証コード

Try.NETに以下のコードを貼り付けることで、オンラインで検証できます。

Sample.cs
usingSystem;publicclassProgram{publicstaticvoidMain(){// typeof(int?)はNullable<int>を返すConsole.WriteLine($"typeof(int?) = {typeof(int?)}");int?nullableThree=3;int?nullValue=null;intnotNullTen=10;// Nullable<T>.GetType()は未定義のため、object.GetType()が呼ばれる。(ボックス化)// その際HasValue == trueの場合はT型に、falseの場合はnullにボックス化される。(Nullable<int>にはボックス化されない)// int型にボックス化されるため、intを返すConsole.WriteLine($"nullableThree type is {nullableThree.GetType()}");try{// nullにボックス化されるため、NullReferenceExceptionの例外発生Console.WriteLine(nullValue.GetType());}catch(NullReferenceException){Console.WriteLine("nullValue causes NullReferenceException");}// is演算子も同様。n is intとn is int?は同じ結果を返す(Nullable<int>に変えても同様)Console.WriteLine($"nullableThree is int = {nullableThreeisint}");Console.WriteLine($"nullableThree is int? = {nullableThreeisint?}");Console.WriteLine($"nullValue is int = {nullValueisint}");Console.WriteLine($"nullValue is int? = {nullValueisint?}");// int型の変数に対するn is int?に至っては「常にtrueを返すけどいい?」という注釈が出るConsole.WriteLine($"notNullTen is int? = {notNullTenisint?}");// Nullable<int>とintの区別にはNullable.GetUnderlyingType(System名前空間)を使用するConsole.WriteLine($"IsNullableType(notNullTen) = {IsNullableType(notNullTen)}");Console.WriteLine($"IsNullableType(nullableThree) = {IsNullableType(nullableThree)}");// リフレクションでプロパティやフィールドの型を取得した場合はNullable<T>になるConsole.WriteLine(typeof(Foo).GetProperty(nameof(Foo.Value)).PropertyType);}publicclassFoo{publicint?Value{get;set;}}publicstaticboolIsNullableType<T>(To)=>Nullable.GetUnderlyingType(typeof(T))!=null;}
実行結果
typeof(int?)=System.Nullable`1[System.Int32]nullableThreetypeisSystem.Int32nullValuecausesNullReferenceExceptionnullableThreeisint=TruenullableThreeisint?=TruenullValueisint=FalsenullValueisint?=FalsenotNullTenisint?=TrueIsNullableType(notNullTen)=FalseIsNullableType(nullableThree)=TrueSystem.Nullable`1[System.Int32]

参考


Viewing all articles
Browse latest Browse all 8899

Trending Articles