none
更改已装箱对象问题(含代码) RRS feed

  • 问题

  • internal interface IChangeBoxedPoint
    {
        void Change(Int32 x, Int32 y);
    }

    internal struct Point : IChangeBoxedPoint
    {
        private Int32 m_x, m_y;

        public Point(Int32 x, Int32 y)
        {
            m_x = x;
            m_y = y;
        }
           
        public void Change(Int32 x, Int32 y)
        {
            m_x = x;
            m_y = y;
        }

        public override string ToString()
        {
            return String.Format("({0},{1})", m_x, m_y);
        }
    }

    public sealed class Program
    {
        public static void Main()
        {
            Point p = new Point(1, 1);

            Object o = p;
            Console.WriteLine(o);

            ((IChangeBoxedPoint)p).Change(4, 4);
            Console.WriteLine(p);

            ((IChangeBoxedPoint)o).Change(5, 5);
            Console.WriteLine(o);

            Console.ReadKey();
        }
    }

    这段代码运行结果应该是(1,1)(1,1) (5,5),有谁能帮我解释一下?

    2011年10月24日 13:59

答案

  • 请记住:值类型在转化成引用类型的时候总是拷贝自身。

    Point p = new Point(1, 1);
    Object o = p;     //装箱操作
    Console.WriteLine(o);   //直接输出被重写的ToString函数,输出1,1

      ((IChangedBoxedPoint)p).Change(4, 4);  //接口显然是引用类型的。但是注意,p是值类型。你把p强制转化成引用类型的话,相当于p自身拷贝了一次,修改的是拷贝的p的内容,不是p自身的内容,输出的还是1,1

    但是Object是引用类型, ((IChangedBoxedPoint)p).Change(5, 5);  是修改了object中的内容。object中存放的是p的副本。但是照样被修改,输出o自然也就是被修改的副本了。因此得到5,5


    如果你有其它意见或私下交流,请直接发送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)
    慈善点击,点击此处
    • 已标记为答案 bianchunlei 2011年10月25日 14:01
    2011年10月25日 2:18
    版主

全部回复

  • 请记住:值类型在转化成引用类型的时候总是拷贝自身。

    Point p = new Point(1, 1);
    Object o = p;     //装箱操作
    Console.WriteLine(o);   //直接输出被重写的ToString函数,输出1,1

      ((IChangedBoxedPoint)p).Change(4, 4);  //接口显然是引用类型的。但是注意,p是值类型。你把p强制转化成引用类型的话,相当于p自身拷贝了一次,修改的是拷贝的p的内容,不是p自身的内容,输出的还是1,1

    但是Object是引用类型, ((IChangedBoxedPoint)p).Change(5, 5);  是修改了object中的内容。object中存放的是p的副本。但是照样被修改,输出o自然也就是被修改的副本了。因此得到5,5


    如果你有其它意见或私下交流,请直接发送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)
    慈善点击,点击此处
    • 已标记为答案 bianchunlei 2011年10月25日 14:01
    2011年10月25日 2:18
    版主
  • 多谢。

    "值类型在转化成引用类型的时候总是拷贝自身"是指把值类型拷贝到堆上,再进行引用吗?

    ”直接输出被重写的ToString函数“其实是o调用了point类型中被重写的ToString方法,之所以能调用Point类型中的Tostring方法,是因为Object 类型本身也有ToString方法。而不能直接调用Change方法是因为这是Point类型自己定义的方法,Object类没有。可以这样理解吗?这是不是涉及到叫“向上转型”的问题?

    2011年10月25日 14:01
  • "值类型在转化成引用类型的时候总是拷贝自身"是指把值类型拷贝到堆上,再进行引用吗


    Yes。准确说。引用类型的本质是一个指针,是存放在堆中的;而值类型是存放在栈中的。因此引用类型指向值类型的时候,是把原来的值类型靠拷贝一份以后到堆上,然后栈中分配一个指向此堆的指针进行引用。图示:

     

    ”直接输出被重写的ToString函数“其实是o调用了point类型中被重写的ToString方法,之所以能调用Point类型中的Tostring方法,是因为Object 类型本身也有ToString方法。而不能直接调用Change方法是因为这是Point类型自己定义的方法,Object类没有。可以这样理解吗?这是不是涉及到叫“向上转型”的问题?

    父类指向子类,那么父类如果方法是virtual的,子类使用同名、同参、同返回值的override自然重写父类,父类只能调用子类的重写函数了。至于“向上转型”我个人不以为然。子类有的方法父类没有,自然父类无法调用。
    如果你有其它意见或私下交流,请直接发送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年10月26日 1:12
    版主