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

bra*_*orm 6 c# java pointers reference

我是一名Java程序员.我对C#知之甚少.但是从我读过的博客来看,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";
}
Run Code Online (Sandbox Code Playgroud)
  • 步骤1:one在堆上创建具有值的字符串对象,并将其位置的地址存储在变量中ONE.运行时环境在堆上分配一块内存,并返回指向此内存块开头的指针.此变量ONE存储在堆栈中,该堆栈是指向在内存中定位实际对象的引用指针

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

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

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

  • 第5步:changeString调用方法.这个时间参考ONE传递.这意味着本地方法变量word是主范围中变量one 的别名.因此,没有完成参考的副本.因此,它相当于认为将相同的变量传递给方法调用.该方法重新指定变量以指向恰好保持的不同内存位置TWO.该方法返回

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

Java,步骤5是不可能的.那是你做不到的pass by reference.

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


我在这里这里读过的文章.

cod*_*eim 3

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

在 C# 中,默认值是对象引用(一级间接),值类型除外。通过引用传递本质上是将指针传递给对象引用,这是双重间接的。

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

C++

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

void SeedCounter(std::string &word)
{
  word = "TWO";
}
Run Code Online (Sandbox Code Playgroud)

C(忽略 const 等问题)

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

void SeedCounter(char ** word)
{
  *word = strdup("TWO");
}
Run Code Online (Sandbox Code Playgroud)

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

public class StringRef
{
   public string val;
}

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

public static void SeedCounter(StringRef strRefWord)
{
  strRefWord.val = "TWO";
}
Run Code Online (Sandbox Code Playgroud)

根据要求进行详细说明。

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