C# 对象按引用传递或按值传递

本文关键字:按值传递 按引用传递 对象 | 更新日期: 2023-09-27 18:33:23

以下代码的输出让我感到惊讶。我认为"a"应该包含对新创建对象的引用。有人可以解释为什么结果不是 2 吗?

class Program
{
    static void Main(string[] args)
    {
        aclass a = new aclass();
        Process(a);
        Console.WriteLine(a.number);
        Console.ReadLine();
    }
    static void Process(aclass a)
    {
        aclass temp = new aclass();
        temp.number++;
        //Console.WriteLine(temp.number);
        a = temp;
        a.number++;
        //Console.WriteLine(a.number);
    }
}
class aclass
{
    public int number = 0;
}

编辑:这是一个面试问题。我只是意识到我误解了这个概念很长时间。参数 a 与原始 a 不同,尽管它们引用相同的地址。

C# 对象按引用传递或按值传递

您不会更改实际的原始引用,您只是更改参数中保存的引用,这显然是不一样的,更改不会保留回调用方。您可以使用 outref 来更改此行为。

在这种情况下,您特别希望使用ref,因为您还要传入引用。

尝试:

class Program
{
    static void Main(string[] args)
    {
        aclass a = new aclass();
        Process(ref a);
        Console.WriteLine(a.number);
        Console.ReadLine();
    }
    static void Process(ref aclass a)
    {
        aclass temp = new aclass();
        temp.number++;
        //Console.WriteLine(temp.number);
        a = temp;
        a.number++;
        //Console.WriteLine(a.number);
    }
}

请记住,您正在使用 a = temp 分配一个全新的引用。如果您只想更新最初传入的现有类,则可以执行以下操作:

a.number = temp.number;
a.number++;

这将否定对ref的需求。

您可以在 MSDN 上阅读更多信息:

传递引用类型参数

参考关键字

出关键字

这一行aclass a = new aclass();内存中创建一个变量(我们可以存储数据的空间)。考虑它在内存中的地址是*(0x12DF),存储在该位置的value是对象a

这一行Process(a)传递对象a而不是地址VALUEProcess,所以Process()中发生的任何事情都与位置*(0x12DF) contents无关,所以位置*(0x12DF)的内容将保持与调用Process()之前相同。

内容 *(0x12DF) = A

我希望它有帮助,而不是造成更多的混乱!!

基本上是两者之间的区别

  • 按值传递引用类型//进程(a);
  • 通过引用传递引用类型//进程(ref a);

在示例中,Process(a) - 'a' 是一个引用类型,被传递给没有 ref 参数的方法。在这种情况下,指向 的引用副本将传递给该方法。

通过在 Process 方法中使用 new 运算符分配内存的新部分,使变量 'a' 引用 aclass 的新对象。因此,之后的任何更改都不会影响原始对象"a"。

请参阅 MSDN : http://msdn.microsoft.com/en-us/library/s6938f28.aspx