C#中引用类型:继承自System.Object,包括类,数组,接口、委托;
值类型:继承自System.ValueType,包括简单类型,结构,枚举类型
C#中参数传递方式主要分两种,值传递和引用传递,按引用传递必须以ref或者out关键字来修饰,其规则是:方法定义和方法调用必须同时显示的使用ref或者out,否则将导致编译错误;
测试如下:
// 值类型按值传递
private void button1_Click(object sender, EventArgs e)
{
int j = 2;
Change(j);
MessageBox.Show(j.ToString()); // j=2
}
private void Change(int i) // 在栈上建立i,并拷贝j的值
{
i += 5;
MessageBox.Show(i.ToString()); // i=7
}
// 值类型按引用传递1
private void button1_Click(object sender, EventArgs e)
{
// ref传递必须对j进行初始化,否则报错
int j = 2;
Change(ref j);
MessageBox.Show(j.ToString()); // j=7
}
private void Change(ref int i) // i与j公用同一块栈内存
{
i += 5;
MessageBox.Show(i.ToString()); // i=7
}
// 值类型按引用传递2
private void button1_Click(object sender, EventArgs e)
{
// out传递可以不初始化
int j;
Change(out j);
MessageBox.Show(j.ToString()); // j=5
}
private void Change(out int i) // i与j公用同一块栈内存
{
// 注意这里必须初始化i,否则报错
i = 0;
i += 5;
MessageBox.Show(i.ToString()); // i=5
}
// 引用类型按值传递
private void button1_Click(object sender, EventArgs e)
{
StringBuilder build1 = new StringBuilder();
Change(build1);
MessageBox.Show(build1.ToString()); // build1值:"John"
}
private void Change(StringBuilder build2) // build1与build2均在栈中分配内存,但相互独立,且值相等,指向同一块堆内存
{
build2.Append("John"); // build2值:"John"
MessageBox.Show(build2.ToString());
}
// 引用类型按值传递2
private void button1_Click(object sender, EventArgs e)
{
StringBuilder build1 = new StringBuilder();
Change(build1);
MessageBox.Show(build1.ToString()); // build1值:null
}
private void Change(StringBuilder build2) // build1与build2均在栈中分配内存,但相互独立,且值相等,指向同一块堆内存
{
build2 = new StringBuilder("John"); // build2值:"John" ,这里改变build2指向,但build1指向没变
MessageBox.Show(build2.ToString());
}
// 引用类型按引用传递1
private void button1_Click(object sender, EventArgs e)
{
StringBuilder build1 = new StringBuilder();
Change(ref build1);
MessageBox.Show(build1.ToString()); // build1值:"John"
}
private void Change(ref StringBuilder build2) // build2在栈中不重新分配内存,与build1公用,build1与build2同一
{
build2 = new StringBuilder("John"); // build2值:"John" ,这里改变build2指向,也就改变了build1指向
MessageBox.Show(build2.ToString());
}
// 引用类型按引用传递2
private void button1_Click(object sender, EventArgs e)
{
StringBuilder build1 = new StringBuilder();
Change(out build1);
MessageBox.Show(build1.ToString()); // build1值:"John"
}
private void Change(out StringBuilder build2)
{
build2 = new StringBuilder("John"); // build2值:"John"
MessageBox.Show(build2.ToString());
}
总结:值类型按值传递----传递主方法参数中变量值的拷贝
值类型按引用传递----传递主方法参数中变量的地址
引用类型按值传递----传递主方法参数中变量值的拷贝(这个值指向堆中一块内存,相当于复制了一个指针?)
引用类型按引用传递----传递主方法参数中变量的地址