CLR via C#學習筆記-第五章-使用接口更改已裝箱值類型中的字段
阿新 • • 發佈:2018-10-06
就是 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 overrideString 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#,讓他允許這個操作。
使用接口方法的代碼演示
下面是上例的修改版本。
internalinterface 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#學習筆記-第五章-使用接口更改已裝箱值類型中的字段