通过值和参考C#传递

时间:2012-09-27 18:05:41

标签: c#

我知道发送给函数的值默认作为值传递,并且方法接收变量的副本。我知道当一个变量通过引用传递时,该方法可以改变它被调用的变量的值。话虽如此,有人可以帮助解释这些简单插图中发生的事情吗?提前致谢。我猜是表达式是通过引用传递的吗?

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
    }
}

9 个答案:

答案 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;

此时评估xy并将它们添加到一起以存储在ans中,将xy设置为新值以后不< / 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
}

第二个示例中,您将延迟添加,直到您设置新值为止,因此xy的新值将用于计算

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;

不是是一个函数,它是一个被评估并返回的表达式,在此语句执行后更改xy 影响再次ans

要记住的关键点是ans = x + y;在执行语句时评估xyxy的进一步更改不会在此处发挥作用。

答案 4 :(得分:1)

两者之间唯一真正的区别在于,第一个中的return语句返回由ans标识的内存位置保存的值,该值保存值为22。

在第二个中,return语句返回由x标识的内存位置的当前值的值加上y标识的内存位置的当前值,这是当前值的本地值方法(按值传递)并分别由您更改为20和40。那个价值当然是60。

要注意的是传递值的重要部分意味着为值xy分配了本地堆栈内存(或其他),并且不引用值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