none
如何让函数的返回值(引用类型)只读 RRS feed

  • 问题

  • 您好,我有这样一段代码,从一个二叉查找树中找到最小的节点:

    public class BinarySearchTree<T>()
    {
      // properties and members....
      
      private Node<T> root;
    
      public Node<T> FindMinNode()
      {
           Node<T> current = this.root;
           // do sth...
           
           return current;
      }
    }
    

     

    其中Node<T>是我自定义的class,它将被返回。

     

    public class Node<T> 
    {
        public Node<T> LeftChild;
        public Node<T> RightChild;
        public T value;
    }
    

     

    现在的问题是,我可以通过如下的代码破坏BinarySearchTree的结构:

    var bst = new BinarySearchTree<int>();
    // insert..
    
    bst.FindMinNode().LeftChild = new Node<int>();
    
    

    请问如何限制这种修改?

     

    谢谢


     

     

     

     


    Debug my heart...
    2011年7月6日 2:13

答案

  • dear

    所以你要有两个类别一个是给操作的一个是唯读就像

    List<T>是可以让用户Add,Remove

    但ReadOnlyCollection不给Add,Remove壹样的意

    你参考一下:
    http://www.dotblogs.com.tw/yc421206/archive/2011/06/12/28104.aspx
    http://www.dotblogs.com.tw/yc421206/archive/2011/06/17/28786.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    • 已标记为答案 Aspen VJ 2011年7月14日 2:21
    2011年7月8日 2:26

全部回复

  • 楼主好,你的意思是只让“bst.FindMinNode()"返回的值只读的?

    恐怕没有直接的方法,但是考虑“不破坏原来的结构”——

    我建议——

    把Node节点实现IClonable接口,重写里边的方法,进行“深拷贝”(使用序列化或者反序列化的方法),然后Findxxx方法返回一个深拷贝的节点class,这样即便改变,也不会影响原来的class节点了。

    具体可以参考我的博客——

    http://www.cnblogs.com/serviceboy/archive/2009/05/17/1458892.html


    如果你有其它意见或私下交流,请发送邮件到:maledong@qq.com;或者请讨论(Talk)
    If you do not have QQ, please open the page and download it and click the image to talk or leave message for me.
    下载MSDN桌面工具(Vista,Win7)
    下载Technet桌面小工具(Vista,Win7)
    慈善点击,点击此处
    2011年7月6日 3:06
    版主
  • 您好WeiDong

    我刚刚使用了这样的返回语句:

     public Node<T> FindMinNode()
     {
        Node<T> current = this.root;
        // do sth...
        
        return new Node<T>()
        {
          LeftChild=current.LeftChild,
          RightChild=current.RightChild,
          Element=current.Element
        };
     }
    

    使得BST的结构不会被破坏,而且测试了一下,能够达到这样的目的。

    你的博克我下午上班看,有问题再来讨论,先谢谢。


    Debug my heart...
    2011年7月6日 3:33
  • dear

    当为了确保回传的类别,不会被类别的方法给破坏掉,我门可以有两种方式来处理:

    1.一种就是Wei-Dong提出的是回传一个副本,外部使用者无论怎样修改副本都不会影响到类别内部资料

    2.另一种就是建立唯读类别,建立唯读类别的方式就是,另外建立一个类别继承BinarySearchTree,然后把FindMinNode方法用private藏起来,并建立抛出例外的动作或是不动作。

    Node<T> FindMinNode()
    {
       NotSupportedException
    }


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年7月6日 9:39
  • dear

    当为了确保回传的类别,不会被类别的方法给破坏掉,我门可以有两种方式来处理:

    1.一种就是Wei-Dong提出的是回传一个副本,外部使用者无论怎样修改副本都不会影响到类别内部资料

    2.另一种就是建立唯读类别,建立唯读类别的方式就是,另外建立一个类别继承BinarySearchTree,然后把FindMinNode方法用private藏起来,并建立抛出例外的动作或是不动作。

    Node<T> FindMinNode()
    {
       NotSupportedException
    }


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    你好,对于1,你看我上面的那种return是你说的这样吗?

    对于2,请问如果把FindMinNode方法用private藏起来,我外部怎么调用呢?


    Debug my heart...
    2011年7月7日 0:54
  • dear

    所以你要有两个类别一个是给操作的一个是唯读就像

    List<T>是可以让用户Add,Remove

    但ReadOnlyCollection不给Add,Remove壹样的意

    你参考一下:
    http://www.dotblogs.com.tw/yc421206/archive/2011/06/12/28104.aspx
    http://www.dotblogs.com.tw/yc421206/archive/2011/06/17/28786.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    • 已标记为答案 Aspen VJ 2011年7月14日 2:21
    2011年7月8日 2:26
  • hi

    同意余小章的說法~ 值得你參考!


    逐步學習,逐夢踏實;腳步要踩穩,這樣下一步才不會跌倒。 http://www.dotblogs.com.tw/nobel12
    2011年7月8日 2:28
  • hi~

    請問您問題已經解決了嗎?


    逐步學習,逐夢踏實;腳步要踩穩,這樣下一步才不會跌倒。 http://www.dotblogs.com.tw/nobel12
    2011年7月13日 14:15
  • 您好,余小章的博客我看了,我是这样理解他的意思的:

     

    (*) return引用类型之前,将这个引用类型指向的对象拷贝一份,把对拷贝的地址传递出去,这样就不会影响原对象了。

     

    请问是这样吗?

     

    现在的问题是:

    如果ClassA里面含有引用类型的成员,就像 BinarySearchTree 这个类,他有如下成员

    private Node root;

    而这个Node是个引用类型,根据上面(*) 的意思,需要将Node做一个拷贝,但是Node又有子Node,一层一层下去,岂不是要复制很多对象?

     

    比如,对于这样一个二叉树,如果我想把n4返回出来,但是又不希望外面代码修改这棵树的结构,那我是不是应该复制n4以及下面所有的子节点,但如果这棵树很复杂,那我拷贝副本的时间岂不是很久?

              n1

             /  \

           n2   n4

           /    /  \

        n3   n5   n8

                \

                 n6

                /

               n7

     

     


    Debug my heart...
    2011年8月26日 2:33
  • 谢谢,能看看我下面的问题吗?

    我不知道我那样理解你的文章是否正确?


    Debug my heart...
    2011年8月26日 2:34
  • 谢谢,能看看我下面的问题吗?

    我不知道我那样理解你的文章是否正确?


    Debug my heart...

    你只要把每个Node类实现IClone接口就可以,这样你必须实现Clone接口的方法。到时候内部调用就可以了
    如果你有其它意见或私下交流,请直接发送maledong_work@foxmail.com;或者讨论(Talk)
    If you do not have QQ, please open the page and download it and click the image to talk or leave message for me.
    下载MSDN桌面工具(Vista,Win7)
    下载Technet桌面小工具(Vista,Win7)
    慈善点击,点击此处
    2011年8月26日 5:38
    版主
  • 把 Node<T> 定义为 struct.
    2011年8月27日 4:34