[C # Basic Knowledge series] Topic 10: Comprehensive Analysis of Empty Types

Source: Internet
Author: User
Tags unpack

Introduction:

In C #2.0, the void type is also introduced. The Void type is also the value type, but the void type includes the null value type, the following describes the specific support for the null type in C #2.0 (I have been thinking about how to share this article recently, at first, I thought it was relatively simple to use the void type, and I thought it was unnecessary. But considering the integrity of this series, I decided to give it a sigh of relief, hope to be helpful to some unfamiliar people ).

 

I. Why is there an empty type?

If my friends read my previous shares, they will not be unfamiliar with this part, because I usually introduce C # features that often start with this method, because each feature has its own cause (there is a buddhist saying: Everything has a reason, and there is a result ), first of all, let's talk about this cause (the new feature of the null type is added, of course .), When designing a database, we can set the database field to allow null values. If the database field is a date and so on, when the C # language is a value type, when we map a database table to an object, the datetime type cannot be null in the C # language. If this happens, it will conflict with the database design, in this way, developers will have this requirement-can the value type be empty? At the same time, Microsoft also saw that the user had such a requirement. Therefore, Microsoft added a new type in C #2.0, that is, the null type, that is, the value type containing the null value, this is the reason I understand. After introducing the reason, of course, it's just a bit boring. What is the empty type?

II. Introduction to the null type

It is also a value type, but it is a value type that contains null. We can use the following expression to indicate the null type (I believe everyone is familiar with it ):

 int? nullable = null;

The above code is int? It is an int type that can be empty (some people may have such questions. What should I do if I want to make a value type a null type in C #1? Of course, this can be done before C #1, but it will be quite troublesome. If you are interested, you can dig the root "? "This modifier is only a syntactic sugar provided by C # (the so-called syntactic sugar is a convenient form provided by C #. In fact, there must be no Int? This type, this int? The compiler considers the nullable <int> type to be null ), actually, the null type provided by true C #2.0 is -- nullable <t> (this t is the generic parameter described in the previous topic, where T can only be the value type, because the optional null types are defined as: public struct nullable <t> where T: struct) and nullable. The following code describes the use of the null type:

Namespace can be empty type demo {class program {static void main (string [] ARGs) {// the following code can also define int like this? Value = 1; nullable <int> value = 1; console. writeline ("outputs with null values:"); display (value); console. writeline (); console. writeline (); value = new nullable <int> (); console. writeline ("outputs with null type and no value:"); display (value); console. read () ;}// the output method to demonstrate the use of Private Static void display (Int? Nullable) {// The hasvalue attribute indicates whether a null object has a value. // when using the value attribute, you must first determine whether the null type has a value, // If the hasvalue of an empty object returns false, the invalidoperationexception exception is thrown. writeline ("null type value: {0}", nullable. hasvalue); If (nullable. hasvalue) {console. writeline ("value: {0}", nullable. value);} // getvalueordefault (it indicates that if a null object has a value, its value is returned. If a null object does not contain a value, the default value 0 is returned) equivalent to the following statement // If (! Nullable. hasvalue) // {// result = D. value; //} console. writeline ("getvalueordefault (): {0}", nullable. getvalueordefault (); // The getvalueordefault (t) method indicates that if the hasvalue attribute is true, it is the value of the Value Attribute; otherwise, it is the value of the defaultvalue parameter, that is, 2. Console. writeline ("getvalueordefalut overload method use: {0}", nullable. getvalueordefault (2); // gethashcode () indicates the hash code of the object returned by the Value Attribute if the hasvalue attribute is true; if the hasvalue attribute is false, it is zero to the console. writeline ("use of gethashcode () method: {0}", nullable. gethashcode ());}}}

Output result:

The above DEMO code is commented out, and I will not explain it here. To help you understand that the null type is a value type, the intermediate language code is shown below:

3. null merge operator (?? Operator)

?? The operator is the "null merge operator", which indicates two operands. If the number on the left is not null, the number on the left is returned. If the number on the left is null, returns the number on the right. This operator can be used for a null type or a reference type, but cannot be used for a value type (the value type cannot be applied here except for the null type ), because ?? The number on the left must be compared with null. However, the value type cannot be compared with null, so it is not supported ?? Operator), the following uses an example to hide it ?? Use of operators (?? This operator makes it easy to set the default value. It can avoid writing if and else statements in the Code and the number of simple codes, which is helpful for reading .)

 

Static void main (string [] ARGs) {console. writeline ("?? Use the following operators: "); nullcoalescingoperator (); console. Read ();} Private Static void nullcoalescingoperator () {Int? Nullable = NULL; Int? Nullhasvalue = 1 ;//?? Similar to the functions of the three-object operator, // the following code is equivalent to: // X = nullable. hasvalue? B. Value: 12; int x = nullable ?? 12; // at this time, nullhasvalue cannot be null, so the value of Y is nullhasvalue. value, that is, 1 int y = nullhasvalue ?? 123; console. writeline ("null type without value: {0}", x); console. writeline ("null type with value: {0}", Y); // at the same time ?? Operators can also be used for reference types. The following is an example of the reference type console. writeline (); string stringnotnull = "123"; string stringisnull = NULL; // the following code is equivalent to: // (stringnotnull = NULL )? "456": stringnotnull // the following code is also equivalent to: // If (stringnotnull = NULL) // {// return "456 "; //} // else // {// return stringnotnull; //} // you can see from the above equivalent code that there is ?? A large number of IF-else statements can be omitted after the operator, so that the code is less readable and the string result = stringnotnull ?? "456"; string result2 = stringisnull ?? "12"; console. writeline ("when the reference type is not null: {0}", result); console. writeline ("null reference type: {0}", result2 );}

The running result is as follows:

Iv. Empty packing and unpacking

The value type contains the packing and unpacking process, and the empty type also belongs to the value type, which also involves the packing and unpacking process. Here we first introduce the concepts of packing and unpacking, packing refers to the process from the value type to the reference type. unpacking is, of course, the reverse process of packing, that is, the process from the reference type to the value type (here I will further explain the packing and unpacking I understand, first. the net value type is allocated on the stack. However, when the reference type is assigned to the managed stack, the packing process copies the value type value from the push stack to the managed stack, the stack is then pushed to store the reference to the copy value on the managed stack. However, the box is to copy the value on the managed stack to the stack. simply put, packing and unpacking are a process of copying values. Just like moving something from one place to another, we have a deep understanding, you can refer to the blog in the Lower Garden .), the process of packing and unpacking that I understand is in brackets. The following describes how to unpack and unboxing empty types:

When an empty type is assigned to a reference type variable, the CLR will pack the nullable object, first, CLR checks whether the null type is null. If it is null, CLR does not perform the actual packing operation (because null can be directly assigned to a reference type variable ), if the value is not null, CLR obtains the value from an empty type object and boxed the value (this process is the packing process of the value type .), When a boxed value type is assigned to an empty type variable, the CLR will unpack the boxed value type. If the referenced value type is null, in this case, the CLR sets the null type to null (if you think it is too long, you can directly read the following code, and the code will also have detailed comments ). The following is an example to demonstrate the use of empty packing and unpacking. This helps you better understand the concepts described above:

 

Static void main (string [] ARGs) {// console. writeline ("?? Use the following operators: "); // nullcoalescingoperator (); console. writeline ("Empty packing and unpacking are used as follows:"); boxedandunboxed (); console. read () ;}// demonstration of empty-type packing and unpacking Private Static void boxedandunboxed () {// defines an empty-type object nullable <int> nullable = 5; int? Nullablewithoutvalue = NULL; // obtain the type of an empty object. At this time, system is returned. int32, not system. nullable <system. int32>. Pay special attention to the console. writeline ("the null type to be retrieved is {0}", nullable. getType (); // an exception occurs when calling a method of the null type. Therefore, before calling a method of the reference type, it is best to first check whether it is null // console. writeline ("the null type can be retrieved: {0}", nullablewithoutvalue. getType (); // assign an empty type object to the reference type obj. In this case, the boxing operation will take place. You can use boxed in Il to prove that object OBJ = nullable; // obtain the reference type after packing. Is still system. int32, not system. nullable <system. int32> console. writeline ("Get the boxed OBJ type: {0}", obj. getType (); // unpack the variable into a non-empty variable int value = (INT) OBJ; console. writeline ("Unbox to non-empty variables: {0}", value); // Unbox to empty variable nullable = (Int ?) OBJ; console. writeline ("unboxing into empty variables: {0}", nullable); // pack an empty object OBJ = nullablewithoutvalue; console. writeline ("whether obj is null: {0} After null can be empty Type Packing", OBJ = NULL); // unpack it into non-empty variables, in this case, an nullreferenceexception will be thrown, because obj is equal to null after no value can be empty, and an empty address is referenced. // It is equivalent to allocating the null value to an int type variable after unpacking, at this time, of course, the error // value = (INT) OBJ; // console. writeline ("when a non-empty type is packed, it is: {0}", value ); // empty variable nullable = (Int ?) OBJ; console. writeline ("Whether the empty variable is null: {0}", nullable = NULL after the empty type is packed in the box );}

 

Running result:

The above code has been commented out, and the code is relatively simple. I will not explain it here, in fact, empty packing and unpacking operations can be understood as a non-empty packing and unpacking process, but for non-empty type because it contains null values, therefore, CLR checks whether it is null in advance. If it is null, no processing is required. If it is not null, binning and unboxing are performed according to the non-null packing and unboxing processes.

V. Summary

The introduction of this topic is complete. This topic mainly introduces the knowledge about the null type and the null type, I hope this article will help you better understand the empty type. Next topic will introduce it to you.Anonymous MethodThe anonymous method is also a foreshadowing of lambda expressions and LINQ, but it was proposed in C #2, as a result, it can be seen that the addition of Lambda and LINQ in C #3.0 was actually planned by Microsoft as early as C #2.0 and long ago (this is also my inference, however, I don't think it was proposed to put Lambda and LINQ both in C #2, but in C #3.0, I understand the reasons for this: 1. I think Microsoft was definitely trying to propose it together, but later I found that these new features will make major changes to the compiler, it takes a long time to implement it. At this time, the user may not be able to wait and feel that C # does not have many things. Therefore, Microsoft will release the completed part first, however, put Lambda and LINQ in C #3. I think it should be like this, so all the features of C # are closely linked .)

 

  Note: Some netizens reminded me of a major need, so I will add it here. If you are careful, you may find that when the null type is null, at this time, you can still call the hasvalue attribute, that is, if the returned value is false at this time, there may be such a question: why can the attribute be called even if the object is null? Does the nullreferenceexception occur at this time? In fact, I used to find out the cause of this problem. First, the null type is the value type. When the null type is null, in this case, the null type is not null (null in the reference type). It is a valid value type for the null type, therefore, it does not throw an exception when calling hasvalue (the value type cannot be null, but the null type can be null. In this case, null is different from the reference type, which must be clear ). At the same time, this problem also deepens my understanding of the possible empty types. Here we will share it to help you further understand the possible empty types, if you have any comments and C # features, you are welcome to leave a message for me.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.