Nullable<br>を選択します.
9481 ワード
一、紹介
周知のように、値タイプ変数はnullできません.これも、値タイプと呼ばれる理由です.しかし,実際の開発ではnullの値を持つシーンも必要である.たとえば、次のようなシーンがあります.
シーン1:データベーステーブルから空の整数データ列を取得します.データベースのnull値はC#のInt 32タイプに割り当てることができません.
シーン2:UIでプロパティをバインドしますが、一部の値タイプのフィールドは入力する必要はありません(たとえば、ユーザ管理の死亡日).
シーン3:Javaでjava.Util.Dateは参照タイプなので、このタイプのフィールドをnullに設定できます.しかし、CLRではSystem.DateTimeは値タイプであり、DateTime変数はnullできません.Javaを使用して作成されたアプリケーションがCLR上で実行されるWebサービスに日付/時間を伝える場合、Javaアプリケーションの送信がnullの場合、CLRには対応するタイプがありません.
シーン4:関数で値タイプを渡す場合、パラメータの値が指定できず、渡したくない場合は、デフォルト値を使用します.しかし、デフォルト値は最適な選択ではない場合があります.デフォルト値は実際にデフォルトのパラメータ値を渡しているため、論理には特別な処理が必要です.
シーン5:xmlまたはjsonからデータを逆シーケンス化すると、データソースに値タイプ属性の値が不足し、処理が不便になります.
もちろん、私たちの日常の仕事には似たようなことがたくさんあります.
これらの状況から抜け出すために、MicrosoftはCLRに空の値タイプとして使用できる概念を追加した.この点をよりよく理解するためにSystemを見てみましょう.Nullableタイプの論理定義:
上の定義から以下の点をまとめることができます. Nullableタイプも値タイプです. Nullableタイプには、ベース値を表すValue属性と、nullであるか否かを表すBooleanタイプのHasValue属性とが含まれる. Nullableは軽量レベルの値タイプです.Nullableタイプのインスタンス占有メモリのサイズは、値タイプとBooleanタイプ占有メモリのサイズの和に等しい. Nullableの汎用パラメータTは、値タイプでなければならない.Nullableタイプと値タイプを組み合わせてのみ使用できます.ユーザー定義の値タイプも使用できます.
二、文法と使い方
Nullableタイプを使用するには、他の値タイプの汎用パラメータTを1つ指定するだけです.
例:
CLRはまた、簡潔な方法を提供している.
ベースタイプの値は、Value属性で取得できます.以下に示すようにnullでない場合、実際の値が返されます.そうでない場合、InvalidOperationException異常が放出されます.Valueプロパティを呼び出すときにnullであるかどうかを確認する必要があります.
三、タイプの変換と演算
C#は、Nullableタイプを使用する簡単な構文もサポートします.また、Nullableインスタンスの暗黙的な変換と変換もサポートされています.次の例を示します.
Nullableタイプにはオペレータを使用し、含まれるベースタイプと同じ方法で使用します.一元演算子(++、--、-など)は、Nullableタイプ値がnullの場合nullを返します. 二元演算子(+、-、*、/、%、^など)任意のオペランドはnullであり、nullを返します. ==演算子の場合、両方のオペランドがnullの場合、式の計算結果はtrueであり、いずれかのオペランドがnullの場合、式の計算結果はfalseである.両方がnullでない場合は、通常通り比較されます. リレーショナル演算子(>、=、<=)について、いずれかのオペランドがnullの場合、演算結果はfalseであり、オペランドがnullでない場合、この値を比較します. 次の例を参照してください.
Nullableは、参照タイプのように三元オペレータをサポートすることもできます.
四、梱包と解体
Nullableは値のタイプであることはすでに知っていますが、今からその箱詰めと箱の取り外しについて話しましょう.CLRは、Nullableタイプの梱包と解体を処理するために特殊なルールを採用しています.Nullableタイプのインスタンスが箱詰めされると、CLRはインスタンスのHasValueプロパティをチェックします.trueの場合、インスタンスValueプロパティの値を箱詰めして結果を返します.falseを返すとnullに直接戻り、何の処理もしません.箱を分解して処理するときは、箱に入れるのと逆です.CLRは、ボックスを外すオブジェクトがnullであるかどうかをチェックし、新しいインスタンスnew Nullable()を直接作成し、nullでない場合はオブジェクトをタイプTにボックスを外し、新しいインスタンスnew Nullable(t)を作成します.
五、GetType()方法
NullableタイプのGetType()メソッドを呼び出すと、CLRは実際に汎用パラメータのタイプを返します.したがって、NullableインスタンスがInt 32タイプであるかNullableであるかを区別することはできません.次の例を参照してください.
原因分析:
これは、GetType()メソッドを呼び出すと、現在のインスタンスが箱詰めされているためであり、前述の箱詰めと解体の内容に基づいて、ここで実際にはInt 32タイプのGetType()メソッドが呼び出されている.
値タイプのGetType()メソッドを呼び出すと、いずれも箱詰めが発生します.この点については、自分で検証することができます.
六、ToString()方法
NullableタイプのToString()メソッドを呼び出すと、HasValue属性の値がfalseの場合、Stringが戻る.Empty、属性の値がtrueの場合、呼び出される論理はValue.ToString().次の例を参照してください.
七、システムNullableヘルプクラス
マイクロソフトは同じ名前のSystemも提供しています.Nullableの静的クラスは、3つの方法で構成されています.
ここではGetUnderlyingType(Type nullableType)の方法を重点的に説明し、他の2つの方法は値を比較するために使用されているので、自分で研究することができます.
GetUnderlyingType(Type nullableType)メソッドは、nullableTypeパラメータが閉じたNullable汎用でない場合、nullを返すために空のタイプを返すために使用されます.
八、文法糖
マイクロソフトはNullableに豊富な文法糖を提供して開発者の仕事量を減らしています.以下は私が参考にしたいことです.
簡潔に書く
コンパイルされた文
周知のように、値タイプ変数はnullできません.これも、値タイプと呼ばれる理由です.しかし,実際の開発ではnullの値を持つシーンも必要である.たとえば、次のようなシーンがあります.
シーン1:データベーステーブルから空の整数データ列を取得します.データベースのnull値はC#のInt 32タイプに割り当てることができません.
シーン2:UIでプロパティをバインドしますが、一部の値タイプのフィールドは入力する必要はありません(たとえば、ユーザ管理の死亡日).
シーン3:Javaでjava.Util.Dateは参照タイプなので、このタイプのフィールドをnullに設定できます.しかし、CLRではSystem.DateTimeは値タイプであり、DateTime変数はnullできません.Javaを使用して作成されたアプリケーションがCLR上で実行されるWebサービスに日付/時間を伝える場合、Javaアプリケーションの送信がnullの場合、CLRには対応するタイプがありません.
シーン4:関数で値タイプを渡す場合、パラメータの値が指定できず、渡したくない場合は、デフォルト値を使用します.しかし、デフォルト値は最適な選択ではない場合があります.デフォルト値は実際にデフォルトのパラメータ値を渡しているため、論理には特別な処理が必要です.
シーン5:xmlまたはjsonからデータを逆シーケンス化すると、データソースに値タイプ属性の値が不足し、処理が不便になります.
もちろん、私たちの日常の仕事には似たようなことがたくさんあります.
これらの状況から抜け出すために、MicrosoftはCLRに空の値タイプとして使用できる概念を追加した.この点をよりよく理解するためにSystemを見てみましょう.Nullableタイプの論理定義:
1 namespace System 2 { 3 [Serializable] 4 public struct Nullable where T : struct 5 { 6 private bool hasValue; 7 internal T value; 8 9 public Nullable(T value) {10 this.value = value;
11 this.hasValue = true;12 }13 14 public bool HasValue {
15 get {16 return hasValue;
17 }
18 }19 20 public T Value {
21 get {22 if (!HasValue) {
23 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
24 }25 return value;
26 }27 }28 29 public T GetValueOrDefault() {
30 return value;31 }
32 33 public T GetValueOrDefault(T defaultValue) {34 return HasValue ? value : defaultValue;35 }
36 37 public override bool Equals(object other) {
38 if (!HasValue) return other == null;
39 if (other == null) return false;40 return value.Equals(other);
41 }42 43 public override int GetHashCode() {44 return HasValue ? value.GetHashCode() : 0;
45 }46 47 public override string ToString() {
48 return HasValue ? value.ToString() : "";49 }
50 51 public static implicit operator Nullable(T value) {52 return new Nullable(value);53 }
54 55 public static explicit operator T(Nullable value) {
56 return value.Value;
57 }58 }59 }
上の定義から以下の点をまとめることができます.
二、文法と使い方
Nullableタイプを使用するには、他の値タイプの汎用パラメータTを1つ指定するだけです.
例:
1 Nullable i = 1;2 Nullable j = null;3 Nullable> k; // , 。
CLRはまた、簡潔な方法を提供している.
1 int? i = 1;2 int? j = null;
ベースタイプの値は、Value属性で取得できます.以下に示すようにnullでない場合、実際の値が返されます.そうでない場合、InvalidOperationException異常が放出されます.Valueプロパティを呼び出すときにnullであるかどうかを確認する必要があります.
1 Nullable i = 1; 2 Nullable j = null; 3 4 Console.WriteLine(i.HasValue); 5 // :True 6 7 Console.WriteLine(i.Value); 8 // :1 9 10 Console.WriteLine(j.HasValue);11 // :False12 13 Console.WriteLine(j.Value);14 // : System.InvalidOperationException
三、タイプの変換と演算
C#は、Nullableタイプを使用する簡単な構文もサポートします.また、Nullableインスタンスの暗黙的な変換と変換もサポートされています.次の例を示します.
1 // System.Int32 Nullable 2 int? i = 5; 3 4 // 'null' Nullable 5 int? j = null; 6 7 // Nullable Int32 8 int k = (int)i; 9 10 // 11 Double? x = 5; // Int Nullable 12 Double? y = j; // Nullable Nullable
Nullableタイプにはオペレータを使用し、含まれるベースタイプと同じ方法で使用します.
1 int? i = 5; 2 int? j = null; 3 4 // 5 i++; // i = 6 6 j = -j; // j = null 7 8 // 9 i = i + 3; // i = 9 10 j = j * 3; // j = null;11 12 // (==、!=)13 var r = i == null; //r = false14 r = j == null; //r = true15 r = i != j; //r = true16 17 // (、<=、>=)18 r = i > j; //r = false19 20 i = null;21 r = i >= j; //r = false, ,i=null、j=null, >= false
Nullableは、参照タイプのように三元オペレータをサポートすることもできます.
1 // null( ), 0. 2 int age = employee.Age ?? 0;3 4 // 。5 int?[] numbers = {};6 int total = numbers.Sum() ?? 0;
四、梱包と解体
Nullableは値のタイプであることはすでに知っていますが、今からその箱詰めと箱の取り外しについて話しましょう.CLRは、Nullableタイプの梱包と解体を処理するために特殊なルールを採用しています.Nullableタイプのインスタンスが箱詰めされると、CLRはインスタンスのHasValueプロパティをチェックします.trueの場合、インスタンスValueプロパティの値を箱詰めして結果を返します.falseを返すとnullに直接戻り、何の処理もしません.箱を分解して処理するときは、箱に入れるのと逆です.CLRは、ボックスを外すオブジェクトがnullであるかどうかをチェックし、新しいインスタンスnew Nullable()を直接作成し、nullでない場合はオブジェクトをタイプTにボックスを外し、新しいインスタンスnew Nullable(t)を作成します.
1 int? n = null; 2 object o = n; // , null 3 4 Console.WriteLine("o is null = {0}", object.ReferenceEquals(o, null)); 5 // :o is null = True 6 7 8 n = 5; 9 o = n; //o Int3210 11 Console.WriteLine("o's type = {0}", o.GetType());12 // :o's type = System.Int3213 14 o = 5;15 16 // Int32 Nullable 17 int? a = (Int32?)o; // a = 5
18 // Int32 Int32 19 int b = (Int32)o; // b = 520 21 // null22 o = null;23 // null Nullable 24 a = (Int32?)o; // a = null 25 b = (Int32)o; // :NullReferenceException
五、GetType()方法
NullableタイプのGetType()メソッドを呼び出すと、CLRは実際に汎用パラメータのタイプを返します.したがって、NullableインスタンスがInt 32タイプであるかNullableであるかを区別することはできません.次の例を参照してください.
1 int? i = 10;2 Console.WriteLine(i.GetType());3 // :System.Int324 5 i = null;6 Console.WriteLine(i.GetType()); //NullReferenceException
原因分析:
これは、GetType()メソッドを呼び出すと、現在のインスタンスが箱詰めされているためであり、前述の箱詰めと解体の内容に基づいて、ここで実際にはInt 32タイプのGetType()メソッドが呼び出されている.
値タイプのGetType()メソッドを呼び出すと、いずれも箱詰めが発生します.この点については、自分で検証することができます.
六、ToString()方法
NullableタイプのToString()メソッドを呼び出すと、HasValue属性の値がfalseの場合、Stringが戻る.Empty、属性の値がtrueの場合、呼び出される論理はValue.ToString().次の例を参照してください.
1 int? i = 10;2 Console.WriteLine(i.ToString());3 // :104 5 i = null;6 Console.WriteLine(i.ToString() == string.Empty);7 // :True
七、システムNullableヘルプクラス
マイクロソフトは同じ名前のSystemも提供しています.Nullableの静的クラスは、3つの方法で構成されています.
1 public static class Nullable 2 { 3 // 。 4 public static Type GetUnderlyingType(Type nullableType); 5 6 // System.Nullable 。 7 public static int Compare(T? n1, T? n2) where T : struct 8 9 // System.Nullable 。10 public static bool Equals(T? n1, T? n2) where T : struct11 }
ここではGetUnderlyingType(Type nullableType)の方法を重点的に説明し、他の2つの方法は値を比較するために使用されているので、自分で研究することができます.
GetUnderlyingType(Type nullableType)メソッドは、nullableTypeパラメータが閉じたNullable汎用でない場合、nullを返すために空のタイプを返すために使用されます.
1 Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable))); 2 // :System.Int32 3 4 Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable<>)) == null); 5 // :True 6 7 Console.WriteLine(Nullable.GetUnderlyingType(typeof(int)) == null); 8 // :True 9 10 Console.WriteLine(Nullable.GetUnderlyingType(typeof(string)) == null);11 // :True
八、文法糖
マイクロソフトはNullableに豊富な文法糖を提供して開発者の仕事量を減らしています.以下は私が参考にしたいことです.
簡潔に書く
コンパイルされた文
1 int? i = 5; 2 3 int? j = null; 4 5 var r = i != null; 6 7 var v = (int) i; 8 9 i++;10 11 i = i + 3;12 13 r = i != j;14 15 r = i >= j;16 17 var k = i + j;18 19 double? x = 5;20 21 double? y = j;
1 int? i = new int?(5); 2 3 int? j = new int?(); 4 5 var r = i.HasValue; 6 7 var v = i.Value; 8 9 i = i.HasValue ? new int?(i.GetValueOrDefault() + 1) : new int?();10 11 i = i.HasValue ? new int?(i.GetValueOrDefault() + 3) : new int?();12 13 r = i.GetValueOrDefault() != j.GetValueOrDefault() || i.HasValue != j.HasValue;14 15 r = i.GetValueOrDefault() >= j.GetValueOrDefault() && i.HasValue & j.HasValue;16 17 int? k = i.HasValue & j.HasValue ? new int?(i.GetValueOrDefault() + j.GetValueOrDefault()) : new int?();18 19 double? x = new double?((double) 5);20 21 double? y = j.HasValue ? new double?((double) j.GetValueOrDefault()) : new double?();