我知道发送给函数的值默认作为值传递,并且方法接收变量的副本。我知道当一个变量通过引用传递时,该方法可以改变它被调用的变量的值。话虽如此,有人可以帮助解释这些简单插图中发生的事情吗?提前致谢。我猜是表达式是通过引用传递的吗?
using System;
class Program
{
static void Main(string[] args)
{
int x = 2;
int y = 20;
Console.WriteLine(Add(x, y));
}
static int Add(int x, int y)
{
int ans = x + y;
x = 20;
y = 40;
// return x+y;
return ans;
//returns 22
}
}
然后
using System;
class Program
{
static void Main(string[] args)
{
int x = 2;
int y = 20;
Console.WriteLine(Add(x, y));
}
static int Add(int x, int y)
{
int ans = x + y;
x = 20;
y = 40;
return x+y;
// return ans;
//returns 60
}
}
答案 0 :(得分:2)
没有什么奇怪的事情发生,也没有任何关于如何传递参数的内容。
在第一个例子中:
// parameters in: x = 2, y = 20.
int ans = x + y;
// now ans contains the value 22.
x = 20;
y = 40;
// now x and y has changed, but the value in ans
// is already calculated and doesn't change.
return ans;
// returns 22;
在第二个例子中:
// parameters in: x = 2, y = 20.
int ans = x + y;
// now ans contains the value 22.
x = 20;
y = 40;
// now x and y has changed, but not ans.
return x+y;
// the value of the expression is calculated with the current
// values, and 60 is returned.
// the variable ans still contains 22, but that isn't used here.
答案 1 :(得分:1)
在第一种情况下,Add
返回x + y。在第二种情况下,Add
返回20 + 40;
在函数中指定值时,可以更改变量的本地副本。不是实际值。
例如:
using System;
class Program
{
static void Main(string[] args)
{
int x = 2;
int y = 20;
Console.WriteLine(Add(x, y));
// x is still 2, y is still 20
}
static int Add(int x, int y)
{
int ans = x + y;
// You calculate the parameters and store it in the local variable
x = 20;
y = 40;
// You've adapted your local COPIES of the variables
return ans;
// You return the answer which was calculated earlier
}
}
但是,这是因为您正在处理值类型(struct
)。如果您正在处理引用类型(class
),那么这是另一回事,例如:
using System;
class Program
{
private class Numbers
{
public int X;
public int Y;
}
static void Main(string[] args)
{
Numbers num = new Numbers();
num.x = 2;
num.y = 20;
Console.WriteLine(Add(num)); // Prints 2 + 20 = 22
// num.x is now 20, and num.y is now 40
Console.WriteLine(Add(num)); // Prints 20 + 40 = 60
}
static int Add(Numbers num)
{
int ans = num.x + num.y;
// You calculate the result from the public variables of the class
num.x = 20;
num.y = 40;
// You change the values of the class
return ans;
// You return the answer which was calculated earlier
}
}
在C#中,传递参数有4种“类型”:
struct
)。class
)。演示这4个的简短示例:
static void Main()
{
int x = 5; // Value type
List<int> list = new List<int>(new [] { 1, 2, 3 }); // Reference type
ValueByValue(x); // x is still 5
ReferenceByValue(list) // list still contains { 1, 2, 3 }
ValueByReference(ref x); // x is now 10
ReferenceByReference(ref list); // list is now a new list containing only { 4, 5, 6 }
}
static void ValueByValue(int x)
{
x = 10; // Changes local COPY of x
}
static void ReferenceByValue(List<int> list)
{
list = new List<int>(new [] { 4, 5, 6 }); // Changes local COPY of list
}
static void ValueByReference(ref int x)
{
x = 10; // Changes the actual x variable in the Main method
}
static void ReferenceByReference(ref List<int> list)
{
list = new List<int>(new [] { 4, 5, 6 }); // Changes the actual list in the Main method
}
答案 2 :(得分:1)
在这两种情况下,它都是按值传递的。
但是在第二种情况下,如果你试图在调用函数中打印x和y的值,它将仅返回x = 2和y = 20.
x = 20且y = 40刚刚在第二种情况的add函数中更改,它们不会返回修改为调用者。
答案 3 :(得分:1)
这两个都说明了传值,通常是值类型语义。
在第一个示例中,您说:
int ans = x + y;
此时评估x
和y
并将它们添加到一起以存储在ans中,将x
和y
设置为新值以后不< / em>影响ans
的值。
以这种方式考虑:
static int Add(int x, int y)
{
int ans = x + y; // evaluates ans = x + y = 2 + 20 = 22
x = 20; // here ans = 22, x = 20, y = 20
y = 40; // here ans = 22, x = 20, y = 40
return ans; // returns ans which is still 22 since x & y are independent
}
在第二个示例中,您将延迟添加,直到您设置新值为止,因此x
和y
的新值将用于计算
return x + y;
所以,从本质上讲,你得到:
static int Add(int x, int y)
{
int ans = x + y; // ans = 22, x = 2, y = 20
x = 20; // ans = 22, x = 20, y = 20
y = 40; // ans = 22, x = 20, y = 40
return x+y; // evaluates x + y = 60
}
我认为可能令你困惑的是:
ans = x + y;
不是是一个函数,它是一个被评估并返回的表达式,在此语句执行后更改x
或y
不影响再次ans
。
要记住的关键点是ans = x + y;
在执行语句时评估x
和y
。 x
和y
的进一步更改不会在此处发挥作用。
答案 4 :(得分:1)
两者之间唯一真正的区别在于,第一个中的return语句返回由ans
标识的内存位置保存的值,该值保存值为22。
在第二个中,return语句返回由x
标识的内存位置的当前值的值加上y
标识的内存位置的当前值,这是当前值的本地值方法(按值传递)并分别由您更改为20和40。那个价值当然是60。
要注意的是传递值的重要部分意味着为值x
和y
分配了本地堆栈内存(或其他),并且不引用值x and
来自来电者的方法。
答案 5 :(得分:1)
表达式总是产生 RVALUE ..
示例会有所帮助
int x=50,y=20;
- &GT;的右值强>
你不能给rvalue分配任何东西。
Example
x+y=500;//INVALID
- &GT;的左值强>
您可以为其指定值。
Example
x=500;//VALID
y=545*33+4;//VALID
因此,表达式永远不能通过引用传递
答案 6 :(得分:0)
这里的参数是按值传递的。它只是在第二个例子中,因为x和y分别被修改为20和40,所以60作为两者的总和返回。
答案 7 :(得分:0)
static int Add(int x, int y)
{
int ans = x + y;
x = 20;
y = 40;
// return x+y;
return ans;
//returns 22
}
在此方法中,计算在修改之前进行,因此在变量更改之前存储。
static int Add(int x, int y)
{
int ans = x + y;
x = 20;
y = 40;
return x+y;
// return ans;
//returns 60
}
在此方法中,未使用ans
变量,更改x和y值,然后返回x + y
的数学结果,而不是ans
。
此外,其中任何一种方法的 none 都是通过引用传递的,它们都是按值传递,传递引用方法的参数前面有ref
关键字。
static int Add(ref int x, int y) // x is the referenced variable in this example
答案 8 :(得分:0)
这个表达式不是通过引用来调用它唯一的值调用。通过引用调用更改参数的值意味着您正在传递变量的引用。
示例:
using System;
class Program
{
static void Main(string[] args)
{
int x = 2;
int y = 20;
Console.WriteLine("SUM :: " + AddByValue(x, y)); // Call by value
Console.WriteLine("X :: " + x + ", Y :: " + y); // Nothing change to variable
Console.WriteLine("SUM :: " + AddByRef(ref x, ref y)); // Call by reference
Console.WriteLine("X :: " + x + ", Y :: " + y); // Value changed
}
static int AddByValue(int x, int y)
{
int ans = x + y;
x = 20;
y = 40;
return ans;
}
static int AddByRef(ref int x, ref int y)
{
int ans = x + y;
x = 20;
y = 40;
return ans;
}
}
输出
SUM :: 60
X :: 2, Y :: 20
SUM :: 60
X :: 20, Y :: 40