1. 程式人生 > >CLR via C#學習筆記-第五章-使用接口更改已裝箱值類型中的字段

CLR via C#學習筆記-第五章-使用接口更改已裝箱值類型中的字段

就是 nal static 正常 led 垃圾回收 版本 poi over

5.3.1 使用接口更改已裝箱值類型中的字段(以及為什麽不應該這麽做)

下面通過一些例子來驗證自己對值類型、裝箱、拆箱的理解程度。

使用正常方法的代碼演示

internal struct Point{
    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.ToString(),m_y.ToString()); } } public sealed class Program{ public static void Main(){ Point p=new Point(1,1); Console.WriteLine(p);//(1,1),p第一次裝箱 p.Change(2,2); Console.WriteLine(p);//(2,2),p第二次裝箱 Object o=p;//
p第三次裝箱 Console.WriteLine(o);//(2,2) //對o拆箱,將已裝箱Point中的字段復制到線程棧上的一個臨時Point中 //這個臨時Point的字段會改變,但已裝箱的Point不受這個Change調用的影響 ((Point)o).Change(3,3); Console.WriteLine(o);//(2,2) } }

有的語言允許更改已裝箱值類型中的字段,但C#不允許。

不過可以用接口欺騙C#,讓他允許這個操作。

使用接口方法的代碼演示

下面是上例的修改版本。

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.ToString(),m_y.ToString()); } } public sealed class Program{ public static void Main(){ ...
     //對p裝箱,更改已裝箱的對象,但在Change返回後,已裝箱對象立即準備好垃圾回收 ((IChangeBoxedPoint)p).Change(4, 4); Console.WriteLine(p);//(2,2) //o本來就是已裝箱的pOint,調用Change更改已裝箱的對象 ((IChangeBoxedPoint)o).Change(5, 5); Console.WriteLine(o);//(5,5) } }

重要提示

本章提到,值類型應該不可變,也就是說我們不應該定義任何會修改實例字段的成員。

事實上,我建議將值類型的字段都標記為readonly。

本例旨在延時接口方法如何修改已裝箱值類型中的字段。

在C#中,不用接口方法便無法做到。

CLR via C#學習筆記-第五章-使用接口更改已裝箱值類型中的字段