This document is referenced in the speech of Mr. Li Jianzhong.
C # introduce the nullable type, which allows us to assign the value type to null.
In essence, it adds an nullable <t> generic structure type in the framework.
[Serializableattribute ()]
Public struct nullable <t>: iformattable, icomparable, inullablevalue
Where T: valuetype
Take a look at the above declaration, we can determine that nullable is a value type, and the restriction type parameter is a value type.
In addition, C # simplifies the syntax. For more information, see the following section.Code.
Int? X = 3;
Nullable <int> Y = new nullable <int> (3 );
Check the decompilation result.
Nullable <int> nullable1 = new nullable <int> (3 );
Nullable <int> nullable2 = new nullable <int> (3 );
In fact, the compiler will process the abbreviation into a complete structure creation code.
Nullable contains two useful attributes. hasvalue is used to determine whether the type is null. If it is not null, the value of the basic type can be obtained through the value attribute.
When its value is not blank, you can directly use its basic type operators for operations. The getvalueordefault method can obtain the default value of the value or basic type.
Int? X = 3;
Int y = 1;
Console. writeline (x + y );
However, you may find some problems by looking at the decompilation results of this Code.
Nullable <int> nullable1 = new nullable <int> (3 );
Int num1 = 1;
Nullable <int> nullable2 = nullable1;
Int num2 = num1;
Console. writeline (nullable2.get _ hasvalue ()? New nullable <int> (nullable2.getvalueordefault () + num2): New nullable <int> ());
The original simple code became very complex. The Compiler created a new nullable object and determined that the nullable object is null. If it is found that the nullable object is null, the addition operation is abandoned and null is returned directly.
Continue to look at the decompiled il code and the box command appears. Therefore, the cost of the nullable type is very high. Do not use it unless necessary.
. Entrypoint
// Code size: 63 bytes (s)
. Maxstack 3
. Locals Init (
[Mscorlib] system. nullable '1 <int32> nullable1,
Int32 num1,
[Mscorlib] system. nullable '1 <int32> nullable2,
Int32 num2,
[Mscorlib] system. nullable '1 <int32> nullable3)
L_0000: NOP
L_0001: ldloca. s nullable1
L_0003: LDC. i4.3
L_0004: Call instance void [mscorlib] system. nullable '1 <int32 >::. ctor (! 0)
L_0009: NOP
L_000a: LDC. i4.1
L_000b: stloc.1
L_000c: ldloc.0
L_000d: stloc.2
L_000e: ldloc.1
L_000f: stloc.3
L_0010: ldloca. s nullable2
L_0012: Call instance bool [mscorlib] system. nullable '1 <int32 >:: get_hasvalue ()
L_0017: brtrue. s l_0025
L_0019: ldloca. s nullable3
L_001b: initobj [mscorlib] system. nullable '1 <int32>
L_0021: ldloc. s nullable3
L_0023: Br. s l_0033
L_0025: ldloca. s nullable2
L_0027: Call instance! 0 [mscorlib] system. nullable '1 <int32>: getvalueordefault ()
L_002c: ldloc.3
L_002d: add
L_002e: newobj instance void [mscorlib] system. nullable '1 <int32 >::. ctor (! 0)
L_0033: Box [mscorlib] system. nullable '1 <int32>
L_0038: Call void [mscorlib] system. Console: writeline (object)
L_003d: NOP
L_003e: Ret
Finally, I will mention ?? This operator.
The ?? Defines a default value that is returned when a nullable type is assigned to a non-nullable type.
//?? Operator example.
Int? X = NULL;
Int y = x ?? -1; // assigns y to-1 if X is null.
Equivalent
Int y = x. hasvalue? X. getvalueordefault ():-1;