交换方法如何在内存级别的C#中工作?

时间:2014-09-18 20:01:44

标签: java c# pointers reference

我是一名Java程序员。我对C#知之甚少。但是从我读过的blogs开始,Java只支持pass-by-reference-of-reference,而在C#中,默认值是pass-by-reference-of-reference,但程序员可以根据需要使用pass by reference。

我已经了解了交换功能的工作原理。我认为明确这个概念至关重要,因为它对编程概念非常重要。

C#:

public static void Main()
{
  String ONE = "one"; //1
  ChangeString(ONE);  //2
  Console.WriteLine(ONE); //3

  String ONE = "ONE"; //4
  ChangeString(ref ONE); //5
  Console.WriteLine(ONE); //6
}

private static void ChangeString(String word)
{
  word = "TWO";
}
private static void SeedCounter(ref String word)
{
  word = "TWO";
}
  • 步骤1:在堆上创建值为one的字符串对象,并将其位置的地址存储在变量ONE中。运行时环境在堆上分配一块内存,并返回指向此内存块开头的指针。此变量ONE存储在堆栈中,该堆栈是指向内存中实际对象的定位的引用指针

  • 第2步:调用方法changeString。指针的副本(或存储器地址位置)被分配给变量字。此变量是方法的本地变量,这意味着当方法调用结束时,它将从堆栈帧中删除,并且超出范围以进行垃圾回收。 在方法调用中,变量字被重新分配以指向TWO对象在内存中的新位置。方法返回

  • 步骤3:在控制台上打印应打印ONE,因为上一步中更改的内容只是一个局部变量

  • 步骤4:重新分配变量1以指向对象ONE所在的内存位置。

  • 第5步:调用方法changeString。此时对ONE的引用已通过。这意味着本地方法变量字是主范围中变量1的别名。因此,没有复制的引用。因此,它相当于认为将相同的变量传递给方法调用。该方法重新指定变量以指向恰好保留TWO的不同内存位置。该方法返回

  • 步骤6:现在外部作用域上的变量one,即主方法中的变量TWO被方法调用更改,因此它打印Java

pass by reference中,第5步是不可能的。那是你不能{{1}}。

如果我上面描述的编程流程正确,请更正吗?


我读过的文章herehere。 功能

2 个答案:

答案 0 :(得分:3)

您似乎正确理解了语义。只是用其他语言画一些类比..

在C#中,默认值是对象引用(一个间接级别),除了值类型。通过引用传递实际上是传递一个指向对象引用的指针,它是双重间接的。

最接近的是C或C ++类比。

C ++

void ChangeString(std::string word)
{
  word = "TWO";
}

void SeedCounter(std::string &word)
{
  word = "TWO";
}

C(忽略const等问题)

void ChangeString(char * word)
{
  word = strdup("TWO");
}

void SeedCounter(char ** word)
{
  *word = strdup("TWO");
}

但Java类比可能必须是一个带有字符串成员的类:

public class StringRef
{
   public string val;
}

public static void ChangeString(string word)
{
  word = "TWO";
}

public static void SeedCounter(StringRef strRefWord)
{
  strRefWord.val = "TWO";
}

按要求详细说明。

在C#(或更具体的CLR)中,字符串变量是指针,但我们将其称为对象引用。该变量包含一个指向字符串对象的地址,通常位于堆上的某个位置。变量本身通常是一个类字段,它可能存在于堆上,或者是局部变量或参数,因此它存在于堆栈或局部变量槽(也在堆栈中)。当您通过引用传递时,您将传递指向变量的指针,而不是指向最终对象的指针。你的“ref”参数是A,A指向B,它是你的局部变量或对象字段,B指向C,即内存中某处的字符串对象。通过ref传递一个A,它是一个指向B的指针,你现在可以改变B。

答案 1 :(得分:0)

您对通过引用/值传递的语义的理解是正确的。

相关问题