首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按引用传递引用与按值传递引用- C#

按引用传递引用与按值传递引用- C#
EN

Stack Overflow用户
提问于 2010-11-12 06:34:23
回答 4查看 10.5K关注 0票数 3

大家好,

我得到了按值传递和按引用传递的区别。但是通过ref传递引用(比如array)和通过值传递数组似乎是我无法理解的事情。如何通过引用传递引用?

代码语言:javascript
复制
     int[] myArray = {1,2,3};
     PassByVal(myArray);
     PassByRef(ref myArray);

     PassByVal(int[] array)
     {    array = new int[] {7,8,9};   // will not work }

     PassByRef(ref int[] array)
     {    array = new int[] {10,11,12}; }  // will work
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-11-12 06:44:40

我建议你去看看this link。它非常有用,并且包含关于Parameter passing in C#的非常简单的示例。

引用参数不传递函数成员调用中使用的变量的值-它们使用变量本身。不是在函数成员声明中为变量创建新的存储位置,而是使用相同的存储位置,因此函数成员中的变量值和引用参数的值将始终相同。引用参数需要ref修饰符作为声明和调用的一部分-这意味着当你通过引用传递某些东西时,它总是清晰的。让我们看一下前面的示例,只需将参数更改为引用参数:

代码语言:javascript
复制
void Foo (ref StringBuilder x) {
    x = null;
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (ref y);
Console.WriteLine (y==null); // will write TRUE

示例中的

代码语言:javascript
复制
int[] myArray = {1,2,3};
PassByVal(myArray);
PassByRef(ref myArray);

PassByVal(int[] array){
    // the function copy the value of the pointer in a new location of memory
    // the "copied" pointer still points to the array 123    

    // now you are modifying the object pointed by THE COPY of the pointer
    // the original pointer still points to array 123
    // the copy of the pointer will point to array 456
    array = new int[] {7,8,9}; 

} // will not work

PassByRef(ref int[] array){
   // here you are passing the pointer without creating a copy of it in a 
   // new location of memory

   // we have not a original pointer and a "copyed" pointer
   // we have only the original pointer and now whe point it to array 10,11,12
   array = new int[] {10,11,12}; 
}  // will work
票数 2
EN

Stack Overflow用户

发布于 2010-11-12 06:39:08

如果通过引用传递引用,则可以使传入的变量指向新对象。如果通过值传递引用,仍然可以更改对象的状态,但不能使变量指向不同的对象。

示例:

代码语言:javascript
复制
void RefByRef(ref object x)
{
  x=new object(2);
}

void RefByValue(object x)
{
 x=new object(2);//Only changes a local variable and gets discarded once the function exits
}

void Test()
{
  object x1=1;
  object x1a=x1;
  RefByRef(ref x1);
  //x1 is now a boxed 2
  //x1a is still a boxed 1


  object x2=1;
  RefByValue(x2);
  //x2 is still a boxed 1
}
票数 8
EN

Stack Overflow用户

发布于 2010-11-12 07:13:34

为了回答你的问题,让我们先看看ValueTypes,A,ValueType持有这个值。也就是说,它不会依次指向保存该值的另一个内存位置,而是它的内存位置就是该值。

所以int i= 10;

int j= i;

这里发生的是,i的值的副本被赋值给j,它们都有相同的值,但它们在内存中的位置不同。换句话说,每次将一个值类型赋给另一个值类型时,都会创建一个副本。

与ReferenceTypes签订这份合同。

对象o= 10;

对象p= o;

因为o是一个ReferenceType,所以o指向一个值为10的内存位置(它实际上是装箱的,但我将保持它的简单性)。在下一行中,p现在指向相同的内存位置。换句话说,引用类型有两件事。1.地址指针2.保存实际“事物”的实际内存位置(地址所指向的)。

如果你做到了很远,那么我们就可以继续通过值和引用来传递。

在C#中,参数是通过值传递的。因此,如果要将valueType传递给需要值类型参数的方法,则

代码语言:javascript
复制
int i = 10;
SomeMethod(i);
Console.WriteLine(i);

static void SomeMethod(int value)
{
  value = 20;
}

当调用SomeMethod时,会将i的值的副本发送给该方法。如果该方法操作参数,它不会影响原始变量i,所以你在控制台窗口中看到的是10;

将其与引用类型联系起来;

代码语言:javascript
复制
  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

因为c是引用类型。C#通过值传递参数。传递引用的"value“副本。这是c指向的地址的值被传递。在该方法中,由于地址是相同的(它是一个副本,但它指向相同的内存位置),所以该方法能够操作对象的状态。因此,您在控制台窗口中看到的是"John“而不是"Mike”。

但是,如果该方法尝试将另一个实例分配给该参数(在本例中称为"customer“)。然后事情就变了。

代码语言:javascript
复制
  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

请注意,在该方法中,我们创建了一个新的Customer实例,并将其分配给参数customer,并将这个新实例的名称设置为"John“。我们将在控制台窗口中看到的是"Mike“,而不是john。

这是因为在将原始变量(c)传递给该方法之前,已创建了该变量的副本。而现在在这个方法中,我们有了另一个地址,然后操作这个新地址,这样原始实例就不会受到影响。讲得通?

好吧,如果这有意义的话。那么如果我们真的想让SomeMethod能够做我们想要做的事情呢?那么这个参数不能通过值传递,但是它必须通过引用传递。这意味着变量c和两个部分(它所指向的地址值和地址本身)正在被传递。所以现在你是通过引用来传递引用类型。

代码语言:javascript
复制
  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(ref c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(ref Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4159943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档