【问题标题】:Passing an object by value and then by reference按值传递对象,然后按引用传递
【发布时间】:2012-06-20 14:41:40
【问题描述】:

我有以下代码:

   static void Main(string[] args)
    {
        myclass c = new myclass();

        c.test1 = 1;

        myclass c2 = TestPassByValByRef(c);

        Console.WriteLine("c.Test1: {0}", c.test1);
        Console.WriteLine("c2.Test1: {0}", c2.test1);
        Console.ReadLine();
    }

    private static myclass TestPassByValByRef(myclass c)
    {
        Console.WriteLine("Before NowPassByRef c.Test1: {0}", c.test1);
        NowPassByRef(ref c);
        Console.WriteLine("After NowPassByRef c.Test1: {0}", c.test1);

        return c;
    }

    private static void NowPassByRef(ref myclass c)
    {
        c = new myclass();
        c.test1 = 10;
        c.test2 = 25;
    }

输出是 c2 保留更改的值,而 c 没有。 我的问题是:cTestPassByValByRef 中会发生什么?

【问题讨论】:

    标签: c# .net pass-by-reference pass-by-value


    【解决方案1】:

    当您调用TestPassByValByRef 时,您的对象有两个引用——Main 中的引用和TestPassByValByRef 中的参数引用。这是因为在 C# 'by value' 中传递引用类型(不是 struct 的任何内容)实际上是按值传递 reference,而不是对象本身。因此,引用被复制,现在有两个对原始对象的引用。

    在调用NowPassByRef 之后,TestPassByValByRef 的引用副本已被对myclass 的新实例的引用覆盖,但由于Main 中仍有引用,因此该对象不符合条件用于垃圾收集。

    所以,“发生了什么”的简短回答是“什么都没有”。

    【讨论】:

      【解决方案2】:
      static void Main(string[] args)
      {
          myclass c = new myclass();
      
          c.test1 = 1;
      
          myclass c2 = TestPassByValByRef(c);
      
          Console.WriteLine("c.Test1: {0}", c.test1);
          Console.WriteLine("c2.Test1: {0}", c2.test1);
          Console.ReadLine();
      }
      

      main 包含两个引用,这两个引用都可以引用myclass 类型的对象。 cTestPassByValByRef之前被初始化,c2被那个方法的返回值初始化。

      private static myclass TestPassByValByRef(myclass c)
      {
          Console.WriteLine("Before NowPassByRef c.Test1: {0}", c.test1);
          NowPassByRef(ref c);
          Console.WriteLine("After NowPassByRef c.Test1: {0}", c.test1);
      
          return c;
      }
      

      TestPassByValByRef 包含一个名为 c 的引用。它最初包含作为参数传递给它的引用的副本(因为该参数是按值传递的)。 这个引用然后通过引用传递给NowPassByRef并返回。

      private static void NowPassByRef(ref myclass c)
      {
          c = new myclass();
          c.test1 = 10;
          c.test2 = 25;
      }
      

      NowPassByRef 与其调用方法共享引用 c。它在返回之前立即将其重新分配给一个新值。


      你预计会发生什么?

      【讨论】:

        【解决方案3】:

        在第一种情况下,您将 按值 reference 传递给您的对象。

        所以当你在第一种情况中创建new时,你会重新初始化reference副本,因此它失去了与原始对象的关系。

        在第二种情况下,您传递了一个reference 它自己,因此使用new 重新初始化它还会更改它指向的内存位置。

        【讨论】:

        • 我没有投反对票,但很多人试图避免混淆指针和引用,尤其是在两者都存在的语言中(包括 C#)
        • @Damien_The_Unbeliever:改为参考。但是,在 看来,不理解某人的帖子并不能成为投反对票的理由
        【解决方案4】:

        在您的以下代码中,您 c = new myclass();object c 创建一个新的内存引用,它不指向传递的。因此,您不会将更改反映到您创建的第一个对象。

        private static void NowPassByRef(ref myclass c)
            {
                c = new myclass();  // it will create new memory reference
                c.test1 = 10;
                c.test2 = 25;
            }
        

        所以它会显示 c 没有改变并输出为:

        Before NowPassByRef c.Test1: 1
        After NowPassByRef c.Test1: 10
        c.Test1: 1
        c2.Test1: 10
        

        暂时只需在方法中注释c = new myclass();,它将反映对object c 的更改。它将消除您对引用指针等的疑问。

        private static void NowPassByRef(ref myclass c)
                {
                    //c = new myclass();  // it will create new memory reference
                    c.test1 = 10;
                    c.test2 = 25;
                }
        

        现在输出将是:

        Before NowPassByRef c.Test1: 1
        After NowPassByRef c.Test1: 10
        c.Test1: 10
        c2.Test1: 10
        

        我认为这 - C# pass by value/ref? 必须是您对问题的解释信息并检查 John Skeet 在Parameter passing in C#上的文章。

        【讨论】:

        • 要明确一点——我要问的不是为什么该值没有保留其更改的值,而是为什么是。对于此代码示例,我期望发生的事情是使值保持原样。
        • @pm_2:我认为你没有完全回答。我不关注输出,只是向你展示它正在改变参考,你需要通过这些链接......
        猜你喜欢
        • 2015-06-12
        • 2012-01-16
        • 2012-10-14
        • 2014-08-23
        • 2015-05-23
        • 1970-01-01
        • 2016-10-22
        相关资源
        最近更新 更多