In-depth understanding of types and computer systems

Source: Internet
Author: User

In-depth understanding of types and computer systems

In C #, there are two types: Value Type and reference type.

1. Value Type and reference type

An in-depth understanding of these two types is very important. The interviewer will test the interviewer's understanding of these two types of knowledge to determine whether the foundation is solid and whether there is any in-depth thinking.

1.1 What is the value type and reference type?

Value types include simple type, enumeration type, and struct type. A value-type instance is usually allocated to the thread's stack. The variable is stored in the instance data itself.

The instance of the reference type is allocated to the managed stack, and the variable stores the memory address of the instance data. The reference types include the class type, interface type, delegate type, and string type.

For the stack and managed stack, we mentioned this before when I introduced the IL knowledge point. They can be understood as two structures for storing data in the memory.

The following table lists the basic types in C #.

Category

Description

Value Type

Simple Type

Signed integer: int, long, short, sbyte

Unsigned integer: uint, ulong, ushort, byte

Character Type: char

Float: float, double, and decimal with High Precision

Boolean Type: bool

Enumeration type

Enumeration type: enum

Struct type

Struct type: struct

Reference Type

Class type

String type: string

Class type: Console class and custom class type

Array type

One-dimensional array and multi-dimensional data, such as int [] and int [,] (two-dimensional array)

Interface Type

Type defined by the interface keyword

Delegate type

Type defined by the delegate keyword

 

1.2 differences between value types and reference types

This is the focus of the interview. The interviewer often asks questions.

The biggest difference between them is that different memory distributions.

The value type is usually allocated to the thread stack (not absolute), and the reference type is allocated to the managed stack. Different allocation locations lead to different management mechanisms. Management of value types is the responsibility of the operating system, and management of reference types is the responsibility of the garbage collector (GC.

It is useless to say more. First, Let's explain the following code:

Class Program

{

Static void Main (string [] args)

{

// Valuetype is a value type.

Int valuetype = 3;

// Reftype is a reference type

String reftype = "abc ";

}

}

Shows the memory distribution:

The difference between the value type and the reference type lies in the storage location of the actual data: both the value type variables and the actual data are stored in the stack, while the reference type only stores the variables in the stack, the variable stores the actual data address, and the actual data is stored in the managed heap corresponding to the address.

Warning:

As mentioned above, the value type is usually placed on the stack, but this is not absolute. Value Type instances may not always be allocated to the thread stack. When the value type is nested in the reference type, or when the value type is boxed, the value type instance will be allocated to the managed heap.

The nested results include the nested definition of the reference type in the value type and the definition of the value type in the reference type.

1.2.1 nested definition value types in reference types

If the field type of a class is value type, it will be allocated to the managed heap as part of the reference type instance. However, the value types that serve as local variables will still be allocated to the thread stack.

// When the reference type is nested and the value type is defined

Public class NestedValueTypeInRef

{

// Valuetype is assigned to the managed stack as part of the reference type

Private int valuetype = 3;

Public void method ()

{

Char c = 'C'; // because it is a local variable in the method, it will still be stored on the stack.

}

}

Class Program

{

Static void Main (string [] args)

{

NestedValueTypeInRef reftype = new NestedValueTypeInRef ();

}

}

Let's explain it in an image:

1.2.2 nested definition of reference type in Value Type

When the value type is nested to define the reference type, the reference of the reference type is saved on the stack, and the actual data is still saved in the managed heap.

Public class TestClass

{

Public int x;

Public int y;

}

// Value Type nested definition of reference type

Public struct NestedRefTypeValue

{

// Struct field. Note that struct fields cannot be initialized.

Private TestClass classinValuetype;

// Constructor in the structure diagram. Note that constructor without parameters cannot be defined in the struct.

Public NestedRefTypeInValue (TestClass t)

{

ClassinValuetype. x = 3;

ClassinValuetype. y = 5;

ClassinValuetype = t;

}

}

Class Program

{

Static void Main (string [] args)

{

NestedRefTypeInValue valuetype = new NestedRefTypeInValue (new TestClass ());

}

}

The memory allocation in the above Code is shown in:

Summary:

From the two examples above, we can conclude that a value-type instance will always be allocated to the place it declares, and the declared local variable will be allocated to the stack, when declared as a reference type member, it is allocated to the managed stack, while the referenced type instance is always allocated to the managed stack.

The upper par value analyzes the differences between the value type and the reference type in memory distribution. In addition, there are several differences:

(1) The value type inherits from ValueType and ValueType inherits from System. Object. The reference type directly inherits from System. Object.

(2) the memory of the value type is not controlled by GC (Garbage Collector). When the scope ends, the value type is released by the operating system, reducing the pressure on the managed heap; the memory management of the reference type is completed by GC. Therefore, compared with the reference type, the value type has more advantages in performance.

(3) The value type is sealed. You cannot use the value type as the base class of any other type. The reference type is generally inherited, this refers to classes and interfaces.

(4) The value type cannot be null. It is initialized to 0 by default, and the reference type is initialized to null by default, does not point to any address in the managed heap. Any operation of the reference type whose value is null will cause NullReferenceException.

(5) because a value type variable contains actual data, by default, parameter transmission between value types does not affect the variable itself; the reference type variables store the data reference addresses. When they are passed as parameters, the parameters change, thus affecting the value of the type variables.

 

2. parameter transfer problems

By default, parameters in the C # method are passed by value, but there are actually four different parameter passing methods:

(1) Value Type parameter passing by value

(2) pass reference type parameters by value

(3) pass value type parameters by reference

(4) Transmit parameters of reference type by reference

2.1 value type parameter passing by value

The value type is passed by value, passing a copy of the Value Type instance, that is, the form parameter receives a copy of the real parameter, the called method operates on a copy of the real parameter.

Class Program

{

Static void Main (string [] args)

{

// 1. Pass the value type by value

Console. WriteLine ("pass by value of Value Type ");

Int addNum = 1;

Add (addNum );

Console. WriteLine ("the value of the real parameter addNum after the method is called:" + addNum );

Console. ReadKey ();

}

 

// 1. Pass the value type by value

Private static void Add (int addnum)

{

Addnum = addnum + 1;

Console. WriteLine ("addnum value in method:" + addnum );

}

}

The running result is as follows:

From the perspective of memory, it shows the value type parameter passing by value.

2.2 pass reference type parameters by value

When the passed parameter is of the reference type, the target of the transfer and operation is the address of the object, and the actual content transmitted is the copy of the address. Because the address points to the value of the real parameter, when the method operates the address, it actually operates the value pointed to by the address. Therefore, after calling the method, the value of the original real parameter will be modified.

Class Program
{
Static void Main (string [] args)
{
Console. WriteLine ("pass by value of reference type ");
RefClass refClass = new RefClass ();
RefClass. addNum = 1;
AddRef (refClass );
Console. WriteLine ("the value of the real parameter addNum after the method is called:" + refClass. addNum );
Console. ReadKey ();
}

Private static void AddRef (RefClass addnumRef)
{
AddnumRef. addNum + = 1;
Console. WriteLine ("addNum value in method:" + addnumRef. addNum );
}
}

Public class RefClass
{
Public int addNum;
}

Result:

2.3 Special Cases of passing string reference type parameters by value

This is a special method. The string type is also a reference type. However, when passing by value, the passed parameter is not modified because of the change of the form parameter in the method.

Class Program
{
Static void Main (string [] args)
{
Console. WriteLine ("special cases for passing String reference types by value ");
String str = "old string ";
ChangeStr (str );
Console. WriteLine ("str value of the real parameter after the method is called:" + str );
Console. ReadKey ();
}

Private static void ChangeStr (string oldStr)
{
OldStr = "New String ";
Console. WriteLine ("oldStr value in the method:" + oldStr );
}
}

 

According to the analysis in the previous process of "pass by value of reference type parameters", modifying the method on the string will change the value of the real parameter, but the actual running result is not the case. The reason for this particularity is that string is immutable. Once the string type is assigned a value, it cannot be changed, that is, its value cannot be modified through code.

In the method, when the oldStr = "New String" code is executed, the system will re-allocate a memory control to store the New String, and then assign the first address of the allocated memory to the oldStr variable. Therefore, after the method is called, The str variable still points to the old string, while the oldStr variable points to the New String.

2.4 PASS Parameters of the value type and reference type by reference

Whether it is a value type or a reference type, you can use the ref or out keyword to transmit parameters by reference. In addition, when passing by reference, the definition and call of methods must explicitly use the ref and out keywords. They cannot be omitted; otherwise, compilation errors may occur.

Use specific code to describe:

Class Program
{
Static void Main (string [] args)
{
Console. WriteLine ("pass by reference of value type and reference type parameters ");
// Num is a value-type parameter.
Int num = 1;
// RefStr is a real parameter of the reference type.
String refStr = "Old String ";
ChangeByValue (ref num );
Console. WriteLine (num );
ChangeByStr (ref refStr );
Console. WriteLine (refStr );
Console. ReadKey ();
}

Private static void ChangeByStr (ref string numRef)
{
NumRef = "new string ";
Console. WriteLine (numRef );
}

Private static void ChangeByValue (ref int numValue)
{
NumValue = 10;
Console. WriteLine (numValue );
}
}

Result:

It can be seen from the results that the address of the value type variable is transmitted during the value type parameter transfer by reference, and the effect is similar to the value transfer by reference type. The difference is that the address passed by reference is the address of the value type variable on the stack, the address passed by reference type by value is the address of the actual data in the managed heap to which the variable points. When the method operates on the address of the value type variable, the actual data operation is performed on the value type variable, so the value in the real parameter is changed.

When a reference type parameter is passed by reference, the address of the referenced type variable is transmitted, which is the address of the variable on the stack, that is, the reference is passed instead of the reference itself.

 

Conclusion: more hands-on and more thoughts. Understanding the differences between the two types can easily solve interview problems.

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.