byref 与 byval,变量与数组
by ref vs. by val, variable vs. array
可变值:
static void Main(string[] args)
{
int i = 3;
method1(i);
Console.WriteLine(i);
Console.ReadLine();
}
static void method1(int z)
{
z *= 2;
}
输出为 3,因为 method1 没有更改 Main 中的变量。
参考变量:
static void Main(string[] args)
{
int i = 3;
method1(ref i);
Console.WriteLine(i);
Console.ReadLine();
}
static void method1(ref int z)
{
z *= 2;
}
输出为 6,因为 method1 更改了 Main 中的变量。
按值排列:
class Program
{
static void Main(string[] args)
{
int[] i = { 13, 1, 5 };
method1(i);
Console.WriteLine(String.Join(",",i));
Console.ReadLine();
}
static void method1(int[] z)
{
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
}
输出为 26、2、10。
数组参考:
class Program
{
static void Main(string[] args)
{
int[] i = { 13, 1, 5 };
method1(ref i);
Console.WriteLine(String.Join(",",i));
Console.ReadLine();
}
static void method1(ref int[] z)
{
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
}
输出又是 26、2、10。
结论:
变量可以按值或按引用传递,
与只能通过引用传递的数组相反。
这是正确的吗?
如果不是——method1(ref int[] z) 和 method1(int[] z) 有什么区别?我们预计什么时候会得到不同的结果?
当引用类型对象按值传递时,对对象的引用实际上按值传递,因此如果您在方法实现中更新对新对象的引用,引用将开始指向新的内存地址。
您可以通过稍微修改方法实现来查看结果的差异,以便将即将到来的输入数组初始化为新实例,例如:
static void method1(int[] z)
{
z = new int[3]; // new instance created and z has reference to it
// while calling side still refers to old memory location
// which is { 13, 1, 5 }
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
现在,当您调用按值传递方法时,它将仅在本地为此方法修改 z
并且外部数组不会受到影响,而如果您通过引用传递它,那么两个数组都会受到影响变化。
发生的事情是我们通过创建一个新的数组实例将数组 z
设置为引用新的内存位置,因此方法中的引用被更新为指向新的内存位置,但调用方引用仍然指向在调用方法之前实例化的旧数组。
当您通过引用传递时,两个变量都将更新以指向新的内存位置。
static void method1(ref int[] z)
{
z = new int[3]; // new instance created and z has reference to it
// now calling side also refers to new memory location
// which is new int[3];
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
可变值:
static void Main(string[] args)
{
int i = 3;
method1(i);
Console.WriteLine(i);
Console.ReadLine();
}
static void method1(int z)
{
z *= 2;
}
输出为 3,因为 method1 没有更改 Main 中的变量。
参考变量:
static void Main(string[] args)
{
int i = 3;
method1(ref i);
Console.WriteLine(i);
Console.ReadLine();
}
static void method1(ref int z)
{
z *= 2;
}
输出为 6,因为 method1 更改了 Main 中的变量。
按值排列:
class Program
{
static void Main(string[] args)
{
int[] i = { 13, 1, 5 };
method1(i);
Console.WriteLine(String.Join(",",i));
Console.ReadLine();
}
static void method1(int[] z)
{
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
}
输出为 26、2、10。
数组参考:
class Program
{
static void Main(string[] args)
{
int[] i = { 13, 1, 5 };
method1(ref i);
Console.WriteLine(String.Join(",",i));
Console.ReadLine();
}
static void method1(ref int[] z)
{
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
}
输出又是 26、2、10。
结论: 变量可以按值或按引用传递, 与只能通过引用传递的数组相反。 这是正确的吗? 如果不是——method1(ref int[] z) 和 method1(int[] z) 有什么区别?我们预计什么时候会得到不同的结果?
当引用类型对象按值传递时,对对象的引用实际上按值传递,因此如果您在方法实现中更新对新对象的引用,引用将开始指向新的内存地址。
您可以通过稍微修改方法实现来查看结果的差异,以便将即将到来的输入数组初始化为新实例,例如:
static void method1(int[] z)
{
z = new int[3]; // new instance created and z has reference to it
// while calling side still refers to old memory location
// which is { 13, 1, 5 }
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}
现在,当您调用按值传递方法时,它将仅在本地为此方法修改 z
并且外部数组不会受到影响,而如果您通过引用传递它,那么两个数组都会受到影响变化。
发生的事情是我们通过创建一个新的数组实例将数组 z
设置为引用新的内存位置,因此方法中的引用被更新为指向新的内存位置,但调用方引用仍然指向在调用方法之前实例化的旧数组。
当您通过引用传递时,两个变量都将更新以指向新的内存位置。
static void method1(ref int[] z)
{
z = new int[3]; // new instance created and z has reference to it
// now calling side also refers to new memory location
// which is new int[3];
for(int m=0; m<z.Length;m++)
{
z[m] *= 2;
}
}