none
c# 函数返回的是值还是引用? RRS feed

  • 问题

  • int这种只有值的类型就不讨论了,只讨论有引用的类型,如class

    public HashTable Get1()
    {
      HashTable ht = new HashTable(33);
      return ht; // 这里显然是返回一个引用,没啥好说的
    }

    看下面的类成员:
    class Test
    {
      private HashTable m_ht; // 主要是这个
      public Test()
      {
        m_ht = new HashTable(33);
      }

      public HashTable GetTable()
      {
        return m_ht; // 引用?值?还是copy-on-write?
      }
    }

    外部函数
    public void DoTest
    {
      Test t = new Test();
      t.GetTable().Add("key", "value"); // 这句过后,类成员有没有被改掉?
    }

    问题如下:
    如果上面的类成员被改掉了,那如何才能返回一个值类型?用Clone()么?这个接口不是所有的类都有啊
    如果没改掉,如何返回一个引用让他能改……(属性可以实现,但这里只能用函数)

    汗,可能又是基础问题了,c++影响太深,转不过弯来
    霸王
    2010年3月6日 15:29

答案

  • 引用类型和装了箱的对象都在堆上,栈上只能保存它们的引用。

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月6日 21:01
    版主
  • 再补充一下:
    你提到了Clone方法,这个方法实际上是签表复制,也就是把原对象的引用复制给返回值,所以和你现在的写法类似。
    如果想案遭这个思路来实现,可以新构造一个对象,让这个对象和你的字段有同样的值,然后把新对象返回给用户,也就是做深度复制!
    周雪峰
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月7日 2:53
    版主
  • 你好!
         实际上属性本质上就是方法,所以你可以认为是等价的!
    周雪峰
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月7日 4:02
    版主

全部回复

  • 引用类型和装了箱的对象都在堆上,栈上只能保存它们的引用。

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月6日 21:01
    版主
  • 你好!
         class Test
    {
      private HashTable m_ht; // 主要是这个
      public Test()
      {
        m_ht = new HashTable(33);
      }

      public HashTable GetTable()
      {
        return m_ht; // 这里返回引用,就是new HashTable(33);构造的对象的引用。
      }
    }
    public void DoTest
    {
      Test t = new Test();
      t.GetTable().Add("key", "value"); // 这里会修改类中的字段的!
    }
    如果避免把类中字段的引用暴露出来,我在你其他的帖子中已经做了回复了!
    常用的方法有四种:
         1,直接返回值类型给用户,这样用户只能修改你返回对象的一个副本,而不能修改你的内部对象了
         2,直接返回常量类型给用户,例如:string,一旦修改了一个string实例,就会生成一个新的string实例了,你原来的string并不受影 响
         3,返回一个接口给用户,这样用户只能通过接口进行有限的操作了
         4,使用包装器类来限制用户进行的操作,DataView就是这样的类
         希望对你有帮助!
    周雪峰
    2010年3月7日 2:47
    版主
  • 再补充一下:
    你提到了Clone方法,这个方法实际上是签表复制,也就是把原对象的引用复制给返回值,所以和你现在的写法类似。
    如果想案遭这个思路来实现,可以新构造一个对象,让这个对象和你的字段有同样的值,然后把新对象返回给用户,也就是做深度复制!
    周雪峰
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月7日 2:53
    版主
  • 我只是想知道,属性和函数在返回同一个类型的时候是否等价?

    Test.Table(假设作为只读属性,get{ return m_ht;})

    Test.GetTable()

    上面这两种方法是否都获取了内部成员的引用并且可以修改?

    记得看到过c#也有copy-on-write机制,不知函数返回值有没有用这种机制。

    霸王
    2010年3月7日 3:46
  • 你好!
         实际上属性本质上就是方法,所以你可以认为是等价的!
    周雪峰
    • 已标记为答案 Jimt200010 2010年3月7日 5:53
    2010年3月7日 4:02
    版主
  • 多谢,之后就在调试中去研究吧
    霸王
    2010年3月7日 5:52
  • 不客气啊!
    周雪峰
    2010年3月7日 6:14
    版主