Details on the difference between c reference types and value types

  • 2020-05-12 03:12:02
  • OfStack

Resolution: CLR supports two types: value type and reference type. In the words of Jeffrey Richter (author of CLR via C#), "programmers who don't understand the reference type and value type will introduce code into weird traps and performance problems." This requires proper understanding and use of value and reference types.
Value types include the basic types of C# (declared with the keywords int, char, float, etc.), structures (types declared with the struct keyword), and enums (types declared with the enum keyword). The reference types include classes (types declared with the class keyword) and delegates (special classes declared with the delegate keyword).
Each of the types in C# is either a value type or a reference type. So each object is either an instance of a value type or an instance of a reference type. Instances of value types are usually allocated on the thread stack (statically), but in some cases can be stored in the heap. Objects of reference types are always allocated in the process heap (dynamically allocated).
(1) in C#, whether a variable is a value or a reference depends only on its basic data type.
The basic data types of C# are platform-independent. The predefined types of C# are not built into the language, but into.NET Framework. .NET USES the generic type system (CTS) to define the predefined data types that can be used in the intermediate language (IL). All data types in C# are objects. They can have methods, properties, and so on. For example, when declaring an int variable in C#, the declaration is actually an instance of System.Int32 in CTS (generic type system) :

int i;
i = 1;
string s;
s = i.ToString();

(2) System.Object and System.ValueType.
Both reference types and value types inherit from the System.Object class. The difference is that almost all reference types inherit directly from System.Object, while value types inherit from their subclasses, that is, directly from System.ValueType. As a base class for all types, System.Object provides a set of methods that can be found in all types. It includes toString method and clone method. System.ValueType inherits System.Object. It does not add any members, but overrides some of the inherited methods, making them more suitable for value types.
(3) value type.
All value types of C# are implicitly derived from System.ValueType:
Structure: struct (directly derived from System.ValueType).
Value type: Integer, sbyte (alias of System.SByte), short (System.Int16), int (System.Int32), long (System.Int64), byte (System.C.Byte), ushort (System.UInt16), uint (int.UInt32), ulong (System.UInt64), char (System.Char).
Floating point: float (System.Single), double (System.Double).
High-precision decimal type for financial calculations: decimal (System.Decimal).
Type bool: bool (alias for System.Boolean).
A user-defined structure (derived from System.ValueType).
Enumeration: enum (derived from System.Enum).
Nullable type.
Each value type has an implicit default constructor to initialize the default value of that type. Such as:

int i = 0;
 Is equivalent to: 
int i = new int();

When the new operator is used, the default constructor of a particular type is called and a variable is assigned a default value. In the above example, the default constructor assigned the value 0 to i.
All value types are sealed (seal), so no new value type can be derived.
It is worth noting that System.ValueType is directly derived from System.Object. System.ValueType itself is a class type, not a value type. The key is that ValueType overrides the Equals() method so that value types are compared by instance values, not by reference addresses. The Type. IsValueType property can be used 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());
}

(4) reference type
C# has the following reference types:
Array (derived from System.Array)
The user needs to define the following types.
Class: class (derived from System.Object);
Interface: interface (interface is not a "thing", so there is no problem where it is derived from. The interface simply represents an contract convention [contract].
Delegate: delegate (derived from System.Delegate).
object (alias for System.Object);
String: string (alias for System.String).
It can be seen that:
The reference type is the same as the value type in that a struct can implement an interface. Reference types can derive new types, but value types cannot. Reference types can contain null values, but value types cannot. The assignment of a reference type variable copies only the reference of the object, not the object itself. When one value type variable is assigned to another value type variable, the contained value is copied.
(5) memory allocation.
Instances of value types are often stored on the stack. But there are special cases. If an instance of a class has a field of value type, the field is actually kept in the same place as the class instance, in the heap. Objects that reference types, however, are always stored in the heap. If the field of a structure is a reference type, only the reference itself and the structure instance are stored at 1 (on a stack or heap, as the case may be). As shown in the following example:

public struct ValueTypeStruct
{
    private object referenceTypeObject;
    public void Method()
    {
        referenceTypeObject = new object();
        object referenceTypeLocalVariable = new object();
    }
}
ValueTypeStruct valueTypeStructInstance = new ValueTypeStruct();
valueTypeStructInstance.Method();
//referenceTypeObject  and  referenceTypeLocalVariable  Where are they stored ?
 Looking at valueTypeStructInstance , this is 1 It feels like the whole thing is on the stack. But the field referenceTypeObject It's a reference type, a local variable referenceTypeLocalVarible Also a reference type. 
public class ReferenceTypeClass
{
    private int _valueTypeField;
    public ReferenceTypeClass()
    {
        _valueTypeField = 0;
    }
    public void Method()
    {
        int valueTypeLocalVariable = 0;
    }
}
ReferenceTypeClass referenceTypeClassInstance = new ReferenceTypeClass();
// _valueTypeField Where the deposit ?
referenceTypeClassInstance.Method();
// valueTypeLocalVariable Where the deposit ?

The same goes for referenceTypeClassInstance, which itself is a reference type and seems to be deployed in its entirety on the managed heap. But the field _valueTypeField is a value type, and the local variable valueTypeLocalVariable is also a value type. Are they on the stack or on the managed heap?
The correct analysis of the above situation is that the reference type stores a reference in a stack whose actual storage location is in the managed heap. For convenience, the reference type is simply deployed on the managed heap. A value type is always assigned where it is declared, and is stored as a field along with the variable (instance) to which it belongs. Stored on the stack as a local variable.
(6) identify the usage of value type and reference type.
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, then only one allocation is required and the size is 100 times that of SomeType. If SomeType is a reference type, you start with 100 allocates, then each element of the array is null, and then you initialize 100 elements, and you end up with a total of 101 allocates. This will consume more time and cause more memory fragmentation. So, if the primary responsibility of the type is to store data, the value type is appropriate.
1 generally speaking, value types (not polymorphic) are suitable for storing data that can be manipulated by an C# application, while reference types (polymorphic) should be used to define the behavior of the application. We usually create more reference types than value types. We should create a value type if:
The primary responsibility of this type is for data storage.
The common interface for this type is completely defined by some data member access properties.
This type can never be subclassed.
This type does not have polymorphic behavior.
Answer: in C#, whether a variable is a value or a reference depends only on its data type.
The value types of C# include: structs (numeric types, bool types, user-defined structs), enums, nullable types.
The reference types of C# include: array, user-defined class, interface, delegate, object, string. The elements of an array, whether they are reference types or value types, are stored on the managed heap.
The reference type stores a reference in a stack whose actual storage location is in the managed heap. The reference type is simply deployed on the managed push. A value type is always assigned where it is declared: as a field, it is stored along with the variable (instance) to which it belongs; Stored on the stack as a local variable. Value types have better efficiency in memory management, and do not support polymorphism, suitable for data storage carrier; Reference types support polymorphism and are suitable for defining the behavior of an application.

Related articles: