简体   繁体   English

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

[英]c# object pass by reference or pass by value

The output of the following code surprised me. 以下代码的输出让我感到惊讶。 I think "a" should hold a reference to the newly created object. 我认为“a”应该包含对新创建的对象的引用。 Can someone explain why the result is not 2? 有人可以解释为什么结果不是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;
}

Edit: This is an interview question. 编辑:这是一个面试问题。 I just realized I had misunderstood the concept for long time. 我刚刚意识到我长时间误解了这个概念。 The argument a is different to the original a although they reference to the same address. 参数a与原始参数a不同,尽管它们引用相同的地址。

You're not changing the actual original reference you're just changing the reference held in the parameter which subtly isn't the same, the changes aren't persisted back to the caller. 您没有更改实际的原始引用,只是更改参数中保存的引用,这些引用略微不一样,更改不会持久保存回调用者。 You can change this behaviour by using out or ref . 您可以使用outref来更改此行为。

In this case specifically you'd want to use ref as you're also passing a reference in. 在这种情况下,你特别想要使用ref因为你也传递了一个引用。

Try: 尝试:

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);
    }

}

Remember you're assigning a whole new reference with a = temp . 请记住,您正在使用a = temp分配全新的引用。 If you just wanted to update the existing class you originally passed in then you could do: 如果您只想更新最初传入的现有类,那么您可以执行以下操作:

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

This would negate the need for ref . 这将取消对ref的需要。

You can read more on MSDN: 您可以在MSDN上阅读更多内容:

Passing Reference Type Parameters 传递参考类型参数

ref Keyword ref关键字

out Keyword 关键字

This line aclass a = new aclass(); 这行aclass a = new aclass(); creates a variable (Space where we can store data) in memory. 在内存中创建一个变量(我们可以存储数据的空间)。 Consider that its address in memory is *(0x12DF) and the value which is stored at that location is object a 考虑它在内存中的地址是*(0x12DF)并且存储在该位置的value是对象a

This line Process(a) passes the VALUE of object a NOT THE ADDRESS to function Process , so anything happens in Process() has nothing to do with the contents of location *(0x12DF) , so the contents of location *(0x12DF) will remain the same as it was before calling Process() . 这条线Process(a)通过了VALUE对象的a 不是地址运作Process ,所以有什么事情发生的Process()无关与contents定位的*(0x12DF)所以位置的内容*(0x12DF)将保持与调用Process()之前相同。

CONTENTS OF *(0x12DF) = a 内容*(0x12DF) = a

I hope its helpful instead of creating more confusion!! 我希望它有帮助,而不是创造更多的混乱!

It is basically the difference between 它基本上是区别

  • Passing Reference Types by Value // Process(a); 按值传递参考类型//过程(a);
  • Passing Reference Types by References // Process(ref a); 通过引用传递引用类型//处理(ref a);

In the example, Process(a) - 'a' which is a reference type, is passed to the method without the ref parameter. 在该示例中,作为引用类型的过程(a) - 'a'被传递给没有ref参数的方法。 In such a case, a copy of the reference, which points to a, is passed to the method. 在这种情况下,将指向a的引用的副本传递给该方法。

Allocating a new portion of memory by using the new operator inside the Process method makes the variable 'a' reference a new object of aclass. 通过在Process方法中使用new运算符来分配新的内存部分,使变量'a'引用为aclass的新对象。 Thus, any changes after that will not affect the original object 'a'. 因此,之后的任何更改都不会影响原始对象'a'。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM