- Value Type
- Reference Type
Take C # as an example: its value types include sbyte, byte, char, short, ushort, int, uint, long, ulong, float, and double. Of course, there are also decimal and bool. The reference types are string and object.
What I want to say
What I want to say is that the reason why -- Ref and Out confused me was that they did not seriously analyze the different actions it made for different types.
For value type.
The effect of using Ref and Out is almost the same as that of using pointer variables in C. It allows you to operate the original number directly, rather than the Copy operation of the original number. For example:
Using System; namespace leleapplication4
{
/// <Summary>
/// Summary of Class1.
/// </Summary>
Class Class1
{
/// <Summary>
/// Main entry point of the application.
/// </Summary>
[STAThread]
Static void Main (string [] args)
{
Int a = 5;
Int B; squareRef (ref );
SquareOut (out B); Console. WriteLine ("The a in the Main is:" + );
Console. WriteLine ("The B in the Main is:" + B );
} Static void squareRef (ref int x)
{
X = x * x;
Console. WriteLine ("The x in the squareRef is:" + x );
} Static void squareOut (out int y)
{
Y = 10;
Y = y * y;
Console. WriteLine ("The y in the squareOut is:" + y );
}
}
}
The result is -- 25 100 25 100.
In this way, it achieves the same effect as the pointer variable in C.
For the reference type.
It is difficult to understand the reference type.
First, you need to understand this layer-that is, when a method receives a variable of the Reference type, it will get a Copy of the Reference. The Ref keyword can be used to pass references to methods. Therefore, if this function is misused-for example, when an array-type referenced object is passed with the keyword Ref, The called method actually controls the passed reference itself. This will allow the called method to replace the caller's original reference with different objects or even NULL!
. The arrayA variable with the memory address of 2000 actually stores arrays {1, 2, 3, 4 ,......} Memory start address 10000. If fun () uses fun (arrayA []), it will get 10000 of the data, but this 10000 will be placed in a Copy and will not be placed in the 2000 position of the memory. In this case, if we use fun (ref arrayA []), the value we get is 2000 (that is, the reference in arrayA can be modified by the called method, make it no longer point to 10000, or even use NULL to replace 10000. In this way, the data in the 10000 address may be cleared by the garbage collection mechanism .)
There is an example:
Using System;
Using System. Drawing;
Using System. Collections;
Using System. ComponentModel;
Using System. Windows. Forms;
Using System. Data;
Namespace RefOut
{
/// <Summary>
/// Summary of Form1.
/// </Summary>
Public class Form1: System. Windows. Forms. Form
{
Private System. Windows. Forms. Button button1;
Private System. Windows. Forms. Label label1;
/// <Summary>
/// Required designer variables.
/// </Summary>
Private System. ComponentModel. Container components = null;
Public Form1 ()
{
//
// Required for Windows Form Designer support
//
InitializeComponent ();
//
// TODO: add Any constructor code after InitializeComponent calls
//
}
/// <Summary>
/// Clear all resources in use.
/// </Summary>
Protected override void Dispose (bool disposing)
{
If (disposing)
{
If (components! = Null)
{
Components. Dispose ();
}
}
Base. Dispose (disposing );
}
# Region code generated by Windows Form Designer
/// <Summary>
/// The designer supports the required methods-do not use the code editor to modify
/// Content of this method.
/// </Summary>
Private void InitializeComponent ()
{
This. button1 = new System. Windows. Forms. Button ();
This. label1 = new System. Windows. Forms. Label ();
This. SuspendLayout ();
//
// Button1
//
This. button1.Dock = System. Windows. Forms. DockStyle. Top;
This. button1.Location = new System. Drawing. Point (0, 0 );
This. button1.Name = "button1 ";
This. button1.Size = new System. Drawing. Size (480, 32 );
; This. button1.TabIndex = 0;
This. button1.Text = "Display output ";
This. button1.Click + = new System. EventHandler (this. button#click );
//
// Label1
//
This. label1.Location = new System. Drawing. Point (8, 48 );
This. label1.Name = "label1 ";
This. label1.Size = new System. Drawing. Size (456,336 );
This. label1.TabIndex = 1;
This. label1.Text = "label1 ";
//
// Form1
//
This. AutoScaleBaseSize = new System. Drawing. Size (6, 14 );
This. ClientSize = new System. Drawing. Size (480,405 );
This. Controls. Add (this. label1 );
This. Controls. Add (this. button1 );
This. MaximizeBox = false;
This. MinimizeBox = false;
This. Name = "Form1 ";
This. Text = "Ref & Out ";
This. ResumeLayout (false );
}
# Endregion
/// <Summary>
/// Main entry point of the application.
/// </Summary>
[STAThread]
Static void Main ()
{
Application. Run (new Form1 ());
}
Private void button#click (object sender, System. EventArgs e)
{
Int [] firstArray = {1, 2, 3 };
Int [] firstArrayCopy = firstArray;
This. label1.Text = "Test Passing firstArray reference by value ";
This. label1.Text + = "\ n \ nContents of firstArray before calling FirstDouble: \ n \ t ";
For (int I = 0; I <firstArray. Length; I ++)
{
This. label1.Text + = firstArray [I] + "";
}
FirstDouble (firstArray );
This. label1.Text + = "\ n \ nContents of firstArray after calling FirstDouble. \ n \ t ";
For (int I = 0; I <firstArray. Length; I ++)
{
This. label1.Text + = firstArray [I] + "";
}
If (firstArray = firstArrayCopy)
This. label1.Text + = "\ n \ nThe references refer to the same array. \ n ";
Else
This. label1.Text + = "\ n \ nThe reference refer to different arrays. \ n ";
Int [] secondArray = {1, 2, 3 };
Int [] secondArrayCopy = secondArray;
This. label1.Text + = "\ nTest passing secondArray reference by reference .";
This. label1.Text + = "\ n \ nContents of secondArray before calling SecondDouble: \ n \ t ";
For (int I = 0; I <secondArray. Length; I ++)
{
This. label1.Text + = secondArray [I] + "";
}
SecondDouble (ref secondArray );
This. label1.Text + = "\ n \ nContents of secondArray after calling SecondDouble: \ n \ t ";
For (int I = 0; I <secondArray. Length; I ++)
{
This. label1.Text + = secondArray [I] + "";
}
If (secondArray = secondArrayCopy)
This. label1.Text + = "\ n \ nThe reference refer to the same array .";
Else
This. label1.Text + = "\ n \ nThe reference refer to different arrays .";
This. label1.Text + = "\ n ___________________ heshi _________________ \ nsecondarray \ n ";
For (int I = 0; I <secondArray. Length; I ++)
{
This. label1.Text + = secondArray [I] + "";
}
This. label1.Text + = "\ nsecondarraycopy \ n ";
For (int I = 0; I <secondArrayCopy. Length; I ++)
{
This. label1.Text + = secondArrayCopy [I] + "";
}
}
Void FirstDouble (int [] array)
{
For (int I = 0; I <array. Length; I ++)
Array [I] * = 2;
Array = new int [] {11, 12, 13 };
}
Void SecondDouble (ref int [] array)
{
For (int I = 0; I <array. Length; I ++)
{
Array [I] * = 2;
}
Array = new int [] {11, 12, 13 };
}
}
}
The result after running is:
This indicates that the called program has changed the original Reference.
Summary
In general, both the Ref and Out keywords can provide similar functions, and their functions are similar to the pointer variables in C. The slight difference is:
- When using Ref parameters, the input parameters must be initialized first. But Out is not required. For Out, initialization must be completed in the method.
- When using Ref and Out, you must note that the Ref or Out keyword must be added to both method parameters and execution methods. To match.
- Out is more suitable for use where multiple Return values are needed, while Ref is used when the method to be called modifies the reference of the caller.