Description: Nullable <T> type, details: nullable type
Directory
I. Introduction
Ii. syntax and usage
Iii. type conversion and Operation
Iv. packing and unpacking
5. GetType () method
6. ToString () method
7. System. Nullable help class
8. Syntactic sugar
I. Introduction
As we all know, value type variables cannot be null, which is why they are called value types. However, in the actual development process, the value also needs to benull
. For example:
Scenario 1: You can retrieve an integer data column that can be empty from a database table.null
The value cannot be assigned to the Int32 type in C;
Scenario 2: You bind attributes to the UI, but some value-type fields are not required (for example, the date of death in personnel management );
Scenario 3: in Java,java.Util.Date
Is a reference type, so you can set this type of fieldnull
. However, in CLR,System.DateTime
It is a value type, and the DateTime variable cannotnull
. If an application written in Java needs to communicate the date/time to the Web Service Running on CLR, if the Java application sendsnull
, CLR does not provide the corresponding type;
Scenario 4: When passing value types in a function, you can use the default value if the parameter value cannot be provided and you do not want to transfer it. But sometimes the default value is not the best choice, because the default value actually passes a default parameter value, and the logic needs special processing;
Scenario 5: When deserializing data from xml or json, the value of a value type attribute is missing from the data source, which is inconvenient to handle.
Of course, there are many similar situations in our daily work.
To get rid of these situations, Microsoft has added the concept of a null value type in CLR. To better understand this, let's take a look.System.Nullable<T>
Type logical definition:
1 namespace System 2 {3 [Serializable] 4 public struct Nullable <T> 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> (T value) {52 return new Nullable <T> (value ); 53} 54 55 public static explicit operator T (Nullable <T> value) {56 return value. value; 57} 58} 59}View Nullable Definitions
The preceding definitions can be summarized as follows:
- The Nullable <T> type is also a value type;
- The Nullable <T> type contains a Value Attribute used to represent the basic Value. It also includes
Boolean
Type HasValue attribute is used to indicate whether the value isnull
;
- Nullable <T> is a lightweight value type. The memory size occupied by Nullable <T> type instances is equal to one value type and one
Boolean
The sum of memory used by the type;
- The generic parameter T of Nullable <T> must be of the value type. You can only use the Nullable <T> type with the value type. You can also use the User-Defined value type.
Ii. syntax and usage
To use the Nullable <T> type, you only need to specify a generic parameter T for other value types.
Example:
1 Nullable <int> I = 1; 2 Nullable <int> j = null; 3 Nullable <int> k; // This is an error syntax and an error is reported during compilation.
CLR also provides a simplified method.
1 int? i = 1;2 int? j = null;
You can use the Value attribute to obtain the Value of the basic type. If notnull
Will return the actual value, otherwise it will throwInvalidOperationException
Exception. You can check whether the Value attribute isnull
.
1 Nullable <int> I = 1; 2 Nullable <int> j = null; 3 4 Console. writeLine (I. hasValue); 5 // output result: True 6 7 Console. writeLine (I. value); 8 // output result: 1 9 10 Console. writeLine (j. hasValue); 11 // output result: False12 13 Console. writeLine (j. value); 14 // throw an exception: System. invalidOperationException
Iii. type conversion and Operation
C # also supports Simple syntax to use the Nullable <T> type. It also supports implicit conversion and conversion of Nullable <T> instances. The following is an example:
1 // implicitly convert from System. Int32 to Nullable <Int32> 2 int? I = 5; 3 4 // implicitly convert from 'null' to Nullable <Int32> 5 int? J = null; 6 7 // The explicit conversion from Nullable <Int32> to Int32 is 8 int k = (int) I; 9 10 // the conversion between the base types is 11 Double? X = 5; // implicit conversion from Int to Nullable <Double> 12 Double? Y = j; // implicitly convert Nullable from Nullable <Int32> <Double>
Use the operator for the Nullable <T> type, which is the same as the basic type usage method.
- Unary operator (++, --,-, etc.), if the Nullable <T> type value is
null
, Returnnull
;
- Binary operators (+,-, *,/, %, ^, etc.) Any operand is
null
, Returnnull
;
- For the = Operator, if both operands are
null
, The expression is calculatedtrue
If any operand isnull
, The expression is calculated as false. If neither of them isnull
, Which is compared as usual.
- For Relational operators (>, <, >=, <=), if any operand is
null
, The calculation result isfalse
If none of the operands arenull
To compare the value.
See the following example:
1 int? I = 5; 2 int? J = null; 3 4 // unary operator 5 I ++; // I = 6 6 j =-j; // j = null 7 8 // binary operator 9 I = I + 3; // I = 9 10 j = j * 3; // j = null; 11 12 // equal sign operator (= ,! =) 13 var r = I = null; // r = false14 r = j = null; // r = true15 r = I! = J; // r = true16 17 // comparison operator (<,>, <=,> =) 18 r = I> j; // r = false19 20 I = null; 21 r = I> = j; // r = false. Note that I = null, j = null, but> = the returned result is false.
Nullable <T> can also support ternary operators like reference types.
1 // if the employee's age returns null (the birth date may not be entered), set the value 0. 2 int Age = employee. age ?? 0; 3 4 // use the ternary operator in an aggregate function. 5 int? [] Numbers ={}; 6 int total = numbers. Sum ()?? 0;
Iv. packing and unpacking
We already know that Nullable <T> is a value type. Now let's talk about its packing and unpacking.
CLR uses a special rule to handle Nullable <T> packing and unpacking. When an Nullable <T> type instance is boxed, CLR checks the HasValue attribute of the instance: If yestrue
, Then the Value of the Instance Value attribute is boxed and the result is returned.false
Directly returnnull
.
In case of unpacking, it is different from the case in case of packing. The CLR checks whether the unpacking object isnull
If you create a new instance, new Nullable <T> (),null
, The object is split into type T, and a new instance new Nullable <T> (t) is created ).
1 int? N = null; 2 object o = n; // No packing operation is performed. The null Value 3 4 Console is returned directly. writeLine ("o is null = {0}", object. referenceEquals (o, null); 5 // output: o is null = True 6 7 8 n = 5; 9 o = n; // o references a boxed Int3210 11 Console. writeLine ("o's type = {0}", o. getType (); 12 // output: o's type = System. int3213 14 o = 5; 15 16 // unpack Int32 type into Nullable <Int32> type 17 int? A = (Int32 ?) O; // a = 5 18 // unpack Int32 type into Int32 type 19 int B = (Int32) o; // B = 520 21 // create a file whose Initialization is null22 o = null; 23 // change null to Nullable <Int32> type 24 a = (Int32 ?) O; // a = null 25 B = (Int32) o; // throw an exception: NullReferenceException
5. GetType () method
When the Nullable <T> type is calledGetType()
Method, the CLR actually returns the type of the generic parameter. Therefore, you may not be able to distinguish whether the Nullable <Int32> instance is of the Int32 or Nullable <Int32> type. See the following example:
1 int? I = 10; 2 Console. writeLine (I. getType (); 3 // The output result is: System. int324 5 I = null; 6 Console. writeLine (I. getType (); // NullReferenceException
Cause analysis:
This is becauseGetType()
Method, the current instance has been boxed, according to the previous part of the packing and unpacking content, here actually calls the Int32 typeGetType()
Method.
Of the call value typeGetType()
You can verify this by yourself.
6. ToString () method
When the Nullable <T> type is calledToString()
If the value of the HasValue attribute isfalse
, ReturnsString.Empty
If the value of this attribute istrue
, The Calling logic isValue.ToString()
. See the following example:
1 int? I = 10; 2 Console. writeLine (I. toString (); 3 // output: 104 5 I = null; 6 Console. writeLine (I. toString () = string. empty); 7 // output result: True
7. System. Nullable help class
Microsoft also providesSystem.Nullable
Static class, including three methods:
1 public static class Nullable 2 {3 // return the specified basic type parameter of the null type. 4 public static Type GetUnderlyingType (Type nullableType); 5 6 // compare two relative values System. Nullable <T> object. 7 public static int Compare <T> (T? N1, T? N2) where T: struct 8 9 // indicates whether the two specified System. Nullable <T> objects are equal. 10 public static bool Equals <T> (T? N1, T? N2) where T: struct11}
Here we will focus onGetUnderlyingType(Type nullableType)
The other two methods are used to compare values. You can study them yourself.
GetUnderlyingType(Type nullableType)
The method is used to return a basic type that can be empty. IfnullableType
If the parameter is not a closed Nullable <T> generic type, returnnull
.
1 Console. writeLine (Nullable. getUnderlyingType (typeof (Nullable <int>); 2 // output result: System. int32 3 4 Console. writeLine (Nullable. getUnderlyingType (typeof (Nullable <>) = null); 5 // output result: True 6 7 Console. writeLine (Nullable. getUnderlyingType (typeof (int) = null); 8 // output: True 9 10 Console. writeLine (Nullable. getUnderlyingType (typeof (string) = null); 11 // output: True
8. Syntactic sugar
Microsoft provides a wide range of syntactic sugar for Nullable <T> to reduce the workload of developers. The following is my reference.
Shorthand |
Compiled statement |
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?(); |
Refer:
- Https://www.codeproject.com/Articles/11854/C-Nullable-Types
- Https://www.codeproject.com/Articles/275471/Nullable-Types-in-Csharp-Net
- Https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/using-nullable-types
- Https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/index
Reprinted please indicate the source, original link: http://www.cnblogs.com/tdfblog/p/Nullable-Types-in-Csharp-Net.html