C#通过引用(ref关键字)问题

本文关键字:关键字 问题 ref 引用 | 更新日期: 2023-09-27 18:00:06

我很难理解C#中ref关键字的确切作用。在我的C++代码中,我创建了一个字符串变量以及指向它的指针和引用变量。我将它传递给Delete或Change函数,不出所料,所有3个变量都在修改中。

但是,使用C#,我将创建变量x,并使用字符串数据对其进行初始化。我正在创建一个变量y,它应该是对x的引用。然后,我使用ref关键字将x传递到ChangeDelete方法中,从而修改方法中的变量以及x。然而,y没有被修改,即使它应该是对x的引用,就像C++中一样。这也不仅仅是字符串的问题,因为我已经用C#对象尝试了上面的测试,并得到了相同的结果。

这是否意味着y在我执行var y = x时按值复制了x

C++

#include <iostream>
using namespace std;
void Delete(string &variable)
{
    variable = "";
}
void Change(string &variable)
{
    variable = "changed data";
}
void main()
{
    string x = "data";
    string *y = &x;
    string &z = x;
    Delete(x);
}

c#

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var x = "data";
            var y = x;
            Change(ref x);
        }

        public static void Delete(ref string variable)
        {
            variable = null;
        }
        public static void Change(ref string variable)
        {
            variable = "changed";
        }
    }
}

C#通过引用(ref关键字)问题

此行:var y=x;使y成为x的副本,而不是c中x的引用#因此,当您调用Changed函数时,它不会发生更改。

似乎没有一种简单的方法可以在C#(或大多数其他语言)中重现相同的C++行为。

当您将非值类型的对象作为参数传递给函数时,对象是按值传递的,但对象内容(属性/字段等)是按引用传递的(您可以从函数内部更改它们),当您使用"ref"关键字传递对象时,对象本身是byref,也可以更改,(这与在c++/c中发送指针与向结构(其本身包含指针)发送双指针相同)。

除了"不安全"代码之外,没有其他方法可以在C#中重现这种行为。即使第二个变量的标识发生变化,C++也无法将指针固定到另一个变量,这在大多数其他语言中都是不可用的。

这不是字符串或任何其他类型的特殊功能。例如,在以下C++代码的末尾,"g"指向更新的"f",该"f"设置为"SomeOtherFoo":

Foo f;
Foo *g = &f;
f = SomeOtherFoo();
//'g' points to the updated 'f'

在"safe"C#中,在以下代码的末尾,"g"仍然是原始对象,而不是"SomeOtherFoo"返回的新对象:

Foo f = new Foo();
Foo g = f;
f = SomeOtherFoo();
//'g' does not point to the updated 'f'

问题的核心是字符串在C#中被视为值类型(基元),而在C++中被视为引用类型。因此,正如Haimovitz博士所写的那样,将一个字符串分配给另一个变量将简单地复制该值。

访问C#中变量的实际指针的一种方法是编写"不安全代码"。https://msdn.microsoft.com/en-us/library/aa288474(v=vs.71).aspx