1. Main content
Basic concepts of type
Value types in depth
Reference type drill-down
Comparison of value types and reference types and their applications
2. Basic Concepts
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, and the predefined types of C # 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,
Features of a common type of system:
- Build a framework that supports cross-language integration, type safety, and high-performance code execution.
- Provides an object-oriented model that supports the complete implementation of multiple programming languages.
- Define the rules that each language must follow to help ensure that objects written in different languages can interact.
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 CLR supports two types: value types and reference 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>).
Value type, the value type instance is typically assigned on the thread's stack (stack) and does not contain any pointers to the instance data, because the variable itself contains its instance data
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
2.1 Memory Depth
2.2.1 Memory mechanism
Where data is allocated in memory depends on the data type of the variable, the value type is allocated on the stack of threads, the reference type is allocated on the managed heap, reclaimed by GC control, and the following code and diagram demonstrate the difference between reference type and value type:
private Static Class Referencevsvalue {
Reference type (because of ' class ')
Private class Someref {public Int32 x;}
Value type (because of ' struct ')
Private struct Someval {public Int32 x;}
public static void Go () {
Someref r1 = new Someref (); Allocate on the heap
Someval v1 = new Someval (); Allocate on stack
r1.x = 5; Lifting hands
v1.x = 5; On stack modification
Console.WriteLine (r1.x); Show "5"
Console.WriteLine (v1.x); Also displays "5"
The left half reflects the situation after executing the above code
Someref r2 = R1; Copy only references (pointers)
Someval v2 = v1; Allocate and copy members on the stack
r1.x = 8; r1.x and r2.x will change
v1.x = 9; Just change v1.x and do not change v2.x
Console.WriteLine (r1.x); Show "8"
Console.WriteLine (r2.x); Show "8"
Console.WriteLine (v1.x); Show "9"
Console.WriteLine (v2.x); Show "5"
The right half reflects what happens after all the code is executed.
}
}
Figure 5-1 Diagram of memory allocation when the code is executed
Someval is declared with a struct, rather than using a common class, a struct declares a value type in C #, and each variable or program has its own stack. Different variables can not be common to a memory address so someref and Someval must occupy a different stack, after the variable is passed, the V1 variable will obviously not affect the V2 data, it can be seen that the stack of V1,V2 contains its actual data, and R1, R2 holds the reference address of its instance data in the stack, and the actual data is stored in the managed heap, so it is possible that different variables hold data references of the same address, and when passed from one reference type variable to the same reference type variable, the reference address is passed instead of the actual data. So changing the value of a variable affects the value of another variable, and the allocation of value and reference type in memory is the root cause of its application, which makes it easy to explain why passing parameters by value does not change the value of the formal parameter, and passing by address changes the parameter value.
Memory allocation points:
When a value type variable is a local variable, the instance is created on the stack, and if the value type variable is a member of the type, it is used as part of the type instance data, and other fields of that type are saved on the managed heap, and the problem is explained in detail in the next nested structure section.
Reference type variable data is persisted on the managed heap, but differs according to the size of the instance, as follows: If the size of the instance is less than 85000Byte, the instance is created on the GC heap, and when the instance size is greater than or equal to 85000byte, the instance is created in the Loh (Large Object Heap).
2.2.2 Nested types
Nested structures are either nested in value types that define reference types or nested in reference type variables that define value types
- Reference type nested value type
public class Nestedvalueinref
{
Aint as part of a reference type will be allocated on the managed heap
private int aInt;
Public Nestedvalueinref
{
Achar is allocated on the thread stack of the code.
char Achar = ' a ';
}
The figure 5-2 memory allocation diagram can be represented as:
- Value types nested reference types
When a reference type is nested in a value type, the memory is allocated as a member variable of the value type, the reference to the member is saved on the stack, and the actual data of the member is saved in the managed heap.
public struct Nestedrefinvalue
{
Public MyClass MyClass;
Public Nestedrefinvalue
{
myclass.x = 1;
Myclass.y = 2;
}
}
Figure 5-3 The memory allocation diagram can be represented as:
C # Value types and reference types (top)