"Go" C # detailed value types and reference type differences

Source: Internet
Author: User
Tags access properties

    1. Common Type System
    2. Value type
    3. Reference type
    4. Value types and reference types in-memory deployments
      1. 1 arrays
      2. 2 Type Nesting
    5. Identify value types and use cases for reference types
    6. 5 Summary of differences between value types and reference types

First, what is a value type and what is a reference type?

Variables of value types in C # store data directly, whereas variables of reference types hold references to data, and data is stored in the data heap.

Value type: Byte,short,int,long,float,double,decimal,char,bool and struct are collectively referred to as value types. After a value-type variable is declared, the compiler allocates memory for it, regardless of whether it has been assigned.

Reference type (reference type): String and class are collectively referred to as reference types. When declaring a class, only a small piece of memory is allocated to the stack to hold an address, at which time it is not allocated a memory space on the heap . When you use new to create an instance of a class, allocate space on the heap and save the address of the space on the heap to a small space allocated on the stack.

Instances of value types are typically allocated on the thread stack (static allocations), but in some cases can be stored in the heap. Objects of reference types are always allocated (dynamically allocated) in the process heap.

The following example illustrates the difference between a value type and a reference type, with the following code:

[CSharp]View PlainCopy
  1. Using System;
  2. Using System.Collections.Generic;
  3. Using System.Linq;
  4. Using System.Text;
  5. Namespace Parameters
  6. {
  7. Class Program
  8. {
  9. static void Main (string[] args)
  10. {
  11. Dowork ();
  12. }
  13. static void Dowork ()
  14. {
  15. int i = 0; //int is a value type
  16. Console.WriteLine (i); //i = 0
  17. Pass.value (i); //value type uses a copy of I, I does not change
  18. Console.WriteLine (i); //i = 0
  19. Wrappendint WI = new Wrappendint (); //Create another instance of class Wrappendint
  20. Console.WriteLine (WI.   number); //0//initialized to 0 by default constructor
  21. Pass.reference (WI); //Call method, WI and Param will reference the same object
  22. Console.WriteLine (WI.   number); //
  23. }
  24. }
  25. class Pass
  26. {
  27. public static void value (int param)
  28. {
  29. param = 42; the//assignment operation uses a copy of the value type parameter that is not affected by the original parameter
  30. }
  31. public static void Reference (wrappendint param) //Create an instance of class Wrappendint
  32. {
  33. Param.  Number = 42; //This parameter is a parameter of a reference type
  34. }
  35. }
  36. Class Wrappendint //classes are reference types
  37. {
  38. public int number;
  39. }
  40. }

The output is:

0

0

0

42

Conceptually, a value type stores its value directly, whereas a reference type stores a reference to its value. These two types are stored in different places in memory. In C #, we must determine the behavior of the type instance when designing the type. This decision is very important, as the CLR via C # author Jeffrey Richter, "programmers who do not understand the difference between reference types and value types will introduce strange bugs and performance issues to the code (I believe that a developer who misunderstands the difference between reference types and value types would introduce subtle bugs and performance issues in to their code.) ". This requires that we understand and use value types and reference types correctly.

1. Common Type System

In C #, whether a variable is a value or a reference depends only on its data type.

The basic data types of C # are defined in a platform-independent manner. C # Predefined types are not built into the language, but are built into the. NET Framework: NET uses the common type System (CTS) to define predefined data types that can be used in intermediate language (IL), all oriented. NET language is eventually compiled into IL, which is compiled into code based on the CTS type.

For example, when declaring an int variable in C #, the declaration is actually an instance of System.Int32 in the CTS. This is of great significance:

    • Ensure mandatory type safety on IL;
    • The implementation is different. NET language interoperability;
    • All data types are objects. They can have methods, attributes, and so on. For example:
int i;
i = 1;
string S;
s = i.tostring ();

The MSDN diagram illustrates how the various types in the CTS are related. Note that instances of types can be just value types or self-describing types, even if those types have subcategories.

2. Value types

All value types in C # are implicitly derived from System.ValueType:

    • struct: struct (directly derived from System.ValueType);
      • Numeric type:
        • Integer: sbyte (alias of System.SByte), short (system.int16), int (System.Int32), Long (System.Int64), Byte (System.Byte), ushort (system.uint16 ), UINT (SYSTEM.UINT32), ULONG (System.UInt64), char (System.Char);
        • Float type: float (system.single), double (system.double);
        • High-precision decimal type for financial calculations: decimal (System.Decimal).
      • BOOL Type: bool (alias of System.Boolean);
      • User-defined struct (derived from System.ValueType).
    • Enum: Enum (derived from System.Enum);
    • Nullable type (derived from system.nullable<t> generic struct, T? is actually an alias of system.nullable<t>).

Each value type has an implicit default constructor to initialize the default value for that type. For example:

int i = new int ();

Equivalent to:

Int32 i = new Int32 ();

Equivalent to:

int i = 0;

Equivalent to:

Int32 i = 0;

When you use the new operator, a specific type of default constructor is called and the variable is assigned the default value. In the example above, the default constructor assigns the value 0 to I. The complete default Values table is available on MSDN.

All value types are sealed (seal), so new value types cannot be derived.

It is important to note that both the reference type and the value type inherit from the System.Object class. The difference is that almost all reference types inherit directly from System.Object, whereas value types inherit their subclasses, that is, they inherit System.ValueType directly. System.ValueType is derived directly from System.Object. That is, System.ValueType itself is a class type, not a value type. The key is that ValueType overrides the Equals () method to compare the value type against the value of the instance, rather than the reference address.

You can use the Type.isvaluetype property to determine whether a type is a value type:

Testtype Testtype = new Testtype ();
if (Testtypetype.gettype (). Isvaluetype)
{
Console.WriteLine ("{0} is value type.", testtype.tostring ());
}
3. Reference types

C # has some of the following reference types:

    • Array (derived from System.Array)
    • The following types are defined by the user:
      • Classes: Class (derived from System.Object);
      • Interface: Interface (interface is not a "thing", so there is no question of where to derive it.) Anders in the C # programming Language, the interface simply represents a convention [contract]);
      • Delegate: Delegate (derived from System.Delegate).
    • Object (alias of System.Object);
    • String: String (alias of System.String).

Can be seen:

    • The reference type and the value type are the same, the struct can also implement the interface;
    • A reference type can derive a new type, while a value type cannot;
    • A reference type can contain a null value, and a value type cannot (a nullable type function allows NULL to be assigned to a value type);
    • The assignment of a reference type variable copies only references to the object, not the object itself. When you assign a value type variable to another value-type variable, the contained value is copied.

For the last article, it is often confusing string. I've seen string variables more efficient than string variables in an earlier version of a book; I also often hear that string is a reference type, string is a value type, and so on. For example:

string S1 = "Hello,";
String s2 = "world!";
String s3 = S1 + s2;//s3 is "Hello, world!"

This does look like a value type assignment. Again such as:

string S1 = "a";
string s2 = S1;
S1 = "B";//s2 is still "a"

Changing the value of S1 has no effect on S2. This makes the string look like a value type. In fact, this is the result of operator overloading, when S1 is changed. NET re-allocates memory for S1 on the managed heap. The purpose of this is to implement a string that is a reference type as a normal semantic literal.

4. Deployment of value types and reference types in memory

Often heard, and often seen in books: value types are deployed on the stack, and reference types are deployed on the managed heap. It's not really that simple.

MSDN says: All reference types are deployed on the managed heap. It's easy to understand. When you create an application type variable:

Object reference = new Object ();

The keyword new allocates memory space on the managed heap and returns an address for that memory space. The reference on the left is on the stack, is a reference, stores a memory address, and the memory (located in the managed heap) that the address points to stores its contents (an instance of System.Object). For convenience, the short reference type is deployed on the managed push.

Then look at the value type. The wording in the C # Language specification is "the struct does not require allocating memory on the heap (however, unlike classes, structs is value types and do not require heap allocation)" instead of "struct in the stack Allocate memory on the ". It's easy to confuse: where is the value type deployed?

4.1 Arrays

Consider arrays:

int[] Reference = new INT[100];

Arrays are reference types by definition, so an int array is, of course, a reference type (that is, reference). GetType (). Isvaluetype is false).

While the elements of an int array are int, by definition, int is a value type (that is, reference[i]. GetType (). Isvaluetype is true). So is the value type element in the reference type array actually on the stack or heap?

If you use WinDbg to see reference[i] in memory, you will find that they are not on the stack, but on the managed heap.

In fact, for arrays:

testtype[] Testtypes = new testtype[100];

If Testtype is a value type, it allocates storage space on the managed heap for elements of 100 value types at a time and automatically initializes these 100 elements, storing the 100 elements in this memory.

If Testtype is a reference type, a space is first allocated to the managed heap for Testtypes, and no elements are automatically initialized at this time (that is, testtypes[i] is null). The storage space for this reference type element is allocated on the managed heap when the code initializes an element later.

4.2 Type Nesting

It's more confusing that a reference type contains a value type, and a value type contains a reference type case:

public class Referencetypeclass
{
private int _valuetypefield;
Public Referencetypeclass ()
{
_valuetypefield = 0;
}
public void Method ()
{
int valuetypelocalvariable = 0;
}
}
Referencetypeclass referencetypeclassinstance = new Referencetypeclass ();//where is _valuetypefield?
Referencetypeclassinstance.method ();//where is valuetypelocalvariable?

public struct VALUETYPESTRUCT
{
Private Object _referencetypefield;
public void Method ()
{
_referencetypefield = new Object ();
Object referencetypelocalvariable = new Object ();
}
}
Valuetypestruct valuetypestructinstance = new Valuetypestruct ();
Valuetypestructinstance.method ();//where is _referencetypefield? And where is referencetypelocalvariable?

See Valuetypestructinstance, this is a structural example, it feels like the whole piece is thrown onto the stack. But the field _referencetypefield is a reference type, and the local variable referencetypelocalvarible is also a reference type.

Referencetypeclassinstance also has the same problem, referencetypeclassinstance itself is a reference type, and it seems that the entire block should be deployed on the managed heap. But field _valuetypefield are value types, local variable valuetypelocalvariable are also value types, are they on the stack or on the managed heap?

The rules are:

    • The reference type is deployed on the managed heap;
    • A value type is always assigned where it is declared: as a field, it is stored as a variable (instance) to which it belongs, and is stored on the stack as a local variable.

Let's analyze the code above. For reference type instances, Referencetypeclassinstance:

    • In terms of context, referencetypeclassinstance is a local variable, so it is deployed on the managed heap and is held by a reference on the stack;
    • The value Type field _valuetypefield is part of the reference type instance referencetypeclassinstance. So follow the reference type instance referencetypeclassinstance deployed on the managed heap (a bit like an array case);
    • Valuetypelocalvariable is a value type local variable, so it is deployed on the stack.

For a value type instance, Valuetypestruct:

    • Depending on the context, the value type instance valuetypestructinstance itself is a local variable rather than a field, so it is on the stack;
    • Its reference type field _referencetypefield does not exist following the problem, must be deployed on the managed heap, and is held by a reference (the reference is part of the valuetypestruct, located on the stack);
    • Its reference type local variable referencetypelocalvariable is apparently deployed on the managed heap and is held by a reference on the stack.

Therefore, it is not right to simply say "value types are stored on the stack, and reference types are stored on the managed heap." Specific analysis of the situation must be specific.

5. Identify value types and use cases for reference types


In C #, we use Struct/class to declare a type as a value type/reference type. Consider the following example:
sometype[] Onetypes = new sometype[100];
If SomeType is a value type, only one allocation is required and the size is 100 times times that of SomeType. If SomeType is a reference type, it requires 100 allocations at the beginning, the element value of the array after the allocation is null, and then the 100 elements are initialized, resulting in a total of 101 allocations. This will consume more time, resulting in more memory fragmentation. Therefore, if the type of responsibility is primarily to store data, the value type is more appropriate.
In general, value types (which do not support polymorphism) are suitable for storing data for C # application operations, whereas reference types (which support polymorphism) should be used to define the behavior of the application. Typically, we create more reference types than value types. If the following conditions are true, then we should create them as value types:
The primary responsibility for this type is for data storage.
The common interface for this type is entirely defined by some data member access properties.
The type can never have subclasses.
The type does not have polymorphic behavior.

5. The difference between the value type and the reference type (summary) is the same point: the reference type can implement the interface, the struct in the value type can implement the interface, and both the reference type and the value type inherit from the System.Object class.
1) Scope aspects
The value types of C # include: struct (numeric type, bool type, user-defined struct), enumeration, nullable type.
The reference types of C # include: arrays, user-defined classes, interfaces, delegates, object, strings.

2) Memory allocation aspect:

The elements of an array are stored on the managed heap, whether they are reference types or value types.

A reference type stores a reference in the stack whose actual storage location is in the managed heap. The abbreviation reference type is deployed on the managed push. A value type is always assigned where it is declared: as a field, it is stored as a variable (instance) to which it belongs, and stored on the stack as a local variable. (Stack memory is automatically freed, heap memory is.) NET will be released by the GC from the dynamic release)

3) Applicable occasions

Value types are more efficient in memory management and do not support polymorphism, and are suitable for use as vectors for storing data; reference types support polymorphism and are suitable for defining the behavior of an application.

    • A reference type can derive a new type, whereas a value type cannot because all value types are sealed (seal);
    • A reference type can contain a null value, and a value type cannot (the nullable type feature allows NULL to be assigned to a value type, such as int? a = null; );
    • The assignment of a reference type variable copies only references to the object, not the object itself. When you assign a value type variable to another value-type variable, the contained value is copied.

It is important to note that both the reference type and the value type inherit from the System.Object class. The difference is that almost all reference types inherit directly from System.Object, whereas value types inherit their subclasses, that is, they inherit System.ValueType directly. That is, System.ValueType itself is a class type, not a value type. The key is that ValueType overrides the Equals () method to compare the value type against the value of the instance, rather than the reference address.

"Go" C # detailed value types and reference type differences

Related Article

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.