. Implementation principle of nullable value type [nullable ] in. Net

Time:2021-12-26

In order to make The value type in. Net can be assigned null. Microsoft has specially added the nullable < T > type, which can also be abbreviated as t?. However, nullable < T > itself is a structure and a value type, so how does it assign null to a value type?

The following explains the implementation principle of nullable < T > by customizing a nullable value type.

Custom nullable value type

struct XfhNullable<T> where T : struct
{
  private T innerValue;
  //This attribute is very important
  public bool HasValue { set; get; }
  public T Value
  {
    get
    {
      return HasValue ? innerValue: throw new InvalidOperationException();
    }
  }
  public XfhNullable(T value)
  {
    this.innerValue= value;
    HasValue = true;
  }
  public T GetValueOrDefault(T value)
  {
    return HasValue ? this.innerValue: value;
  }
  public T GetValueOrDefault()
  {
    return this.innerValue;
  }
}

The structure and function of a nullable value type have been roughly defined. Let’s create an instance of nullable value type to verify.

using static System.Console;
class Program
{
  static void Main()
  {
    //Instantiate using the structure's default parameterless constructor
    XfhNullable<int> num = new XfhNullable<int>();
    WriteLine(num.HasValue);
    WriteLine(null_num.GetValueOrDefault());
  }
}

You can see that the variable num does not contain a value. Calling getvalueordefault() will get its default value of 0;

At this time, when we assign null to the variable num, we will find that the compiler reports an error cannot convert null to ‘xfhnullable < int >’ because it is a non nullable value type. This is because the compiler regards the structure xfhnullable < T > defined by us as a normal value type rather than a nullable value type. Therefore, we also need to add the conversion function between nullable value type and xfhnullable < T >.


public static implicit operator XfhNullable<T>(T? nullabelValue)
{
  if (nullabelValue== null)
  {
    return new XfhNullable<T>();
  }
  return new XfhNullable<T>(nullabelValue.Value);
}

The above code implements the implicit conversion from nullable type to xfhnullable < T >. After adding the above code, it is found that the compiler will no longer report errors. Xfhnullable < T > has become a nullable value type.


static void Main()
{
  XfhNullable<int> null_num = null;
  WriteLine(null_num.HasValue);
}

The property hasvalue in xfhnullable < T > is used to mark whether the current type is null. If so, it returns false; otherwise, it returns true. When hasvalue is false, calling the value property of this type will throw an exception invalidoperationexception. However, the getvalueordefault() method can be called to get the default value of the type.

Nullable < T > type can judge whether the value is null by the operator = =. We can also realize this function by operator overloading:


public static bool operator ==(XfhNullable<T> cn, object obj)
{
  if (cn.HasValue)
  {
    return false;
  }
  return true;
}
public static bool operator !=(XfhNullable<T> cn, object obj)
{
  return !(cn == obj);
}

static void Main()
{
  XfhNullable<int> null_num = null;
  WriteLine(null_num == null);
}

Next, let’s implement the conversion between normal value type and xfhnullable < T >


public static implicit operator XfhNullable<T>(T value)
{
  return new XfhNullable<T>(value);
}
public static explicit operator T(XfhNullable<T> value)
{
  return value.innerValue;
}
static void Main()
{
  XfhNullable<int> null_num = null;
  null_ num = 12;// The int type is implicitly converted to the xfhnullable < int > type
  WriteLine(null_num == null);
  WriteLine(null_num.Value);
  int i = (int)null_ num;// Xfhnullable < int > type cast to int type
  WriteLine(i);
}

Get the type of the instance at run time:


static void Main()
{
  XfhNullable<int> null_num = 12;
  WriteLine(null_num.GetType());
}

This return value is not friendly. We want to return the built-in value type, system Int32, the specific implementation code is as follows:

//Because the GetType method in the object class does not allow subclasses to override (to avoid subclasses hiding their actual types)
//Therefore, the keyword new is used here to hide the GetType method in the object class
public new Type GetType()
{
  return innerValue.GetType();
}

Conclusion: there is no nullable value type

So far, we have customized a nullable value type xfhnullable < T >. Through the above code, it is not difficult to find that the so-called nullable value type does not exist. It marks the null value through the attribute hasvalue, Internally, the value of this type is maintained through the field innervalue (which corresponds to the value field in nullable < T >). If it is assigned null, innervalue is initialized to the initial value of the value type. In other words,Nullable < T > only realizes the assignment of null to the value type at the logical level, giving us a feeling that the value type can be null.

Finally, let’s talk about the packing and unpacking of nullable value types.

When the CLR performs the boxing operation on the nullable < T > instance, it first checks whether it is null. If so, the CLR does not box anything, but directly returns NULL; If the value of the instance is not null, get the value of the instance (value property) and boxing the value.

When unpacking, a null value is returnedNullable<T>()Instance. For a specific value, such as 5, it returnsNullable<T>(5)example.

The above is the whole content of this article. I hope the content of this article can bring some help to your study or work. At the same time, I also hope to support developpaer!