先看下面一段代碼
namespace 使用接口更改已裝箱值類型的字段 { //point是一個值類型 internal struct Point { private Int32 m_x, m_y; public Point(Int32 x, Int32 y) { m_x = x; m_y = y; } public void Change(int x, int y) { m_x = x; m_y = y; } public override string ToString() { return string.Format("({0},{1})", m_x, m_y); //fromat返回指定字符串中一個或多個格式項替換為指定對象的字符串格式 } class Program { } static void Main(string[] args) {
Point p = new Point(1, 1);
Console.WriteLine(p);//顯示(1,1)
p.Change(2, 2);
Console.WriteLine(p);//顯示(2,2)
object o = p;
Console.WriteLine(o);//顯示(2,2)
((Point)o).Change(3, 3);
Console.WriteLine(o);//顯示(2,2)
Console.ReadKey();
} } }
Main在棧上創建一個Point值類型對象並賦值(1,1),第一次調用writeline之前對p進行裝箱,writeline會在已裝箱的Point上調用ToString,像預期中結果為(1,1)
p調用Change方法將數值改為2,第二次調用writeline時再次對p進行裝箱,像預期結果為(2,2)
現在p要進行第三次裝箱,o將引用已裝箱的Point對象,第三次調用writeline會顯示(2,2)
最後希望調用Change來更改已裝箱的Point對象中的字段,但是Object o 對Change方法並不知情所以要先將o轉型為Point。將o轉型為Point要先將o拆箱,並將已裝箱中的字段
復制到線程棧上一個臨時的Point中。這個臨時的Point的m_x,m_y會變成3,3,但是已裝箱的Point不受這個Change調用影響,所以第四次顯示(2,2)
用接口來更改已裝箱值類型的字段
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 使用接口更改已裝箱值類型的字段 { //接口定義一個Change方法 internal interface IChageBoxedPoint { void Change(int x, int y); } //point是一個值類型 internal struct Point: IChageBoxedPoint { private Int32 m_x, m_y; public Point(Int32 x, Int32 y) { m_x = x; m_y = y; } public void Change(int x, int y) { m_x = x; m_y = y; } public override string ToString() { return string.Format("({0},{1})", m_x, m_y); //fromat返回指定字符串中一個或多個格式項替換為指定對象的字符串格式 } class Program { } static void Main(string[] args) { Point p = new Point(1, 1); Console.WriteLine(p);//顯示(1,1) p.Change(2, 2); Console.WriteLine(p);//顯示(2,2) object o = p; Console.WriteLine(o);//顯示(2,2) ((Point)o).Change(3, 3); Console.WriteLine(o);//顯示(2,2) //對p進行裝箱,更改已裝箱的對象,然後丟棄它; ((IChageBoxedPoint)p).Change(4, 4); Console.WriteLine(p);//顯示(2,2)
//更改已裝箱的對象病顯示他 ((IChageBoxedPoint)o).Change(5,5); Console.WriteLine(o);//顯示(5,5)
} } }
這段代碼與上邊的主要區別是change方法由
IChageBoxedPoint接口定義,Point類型實現了這個接口。
//對p進行裝箱,更改已裝箱的對象,然後丟棄它; ((IChageBoxedPoint)p).Change(4, 4); Console.WriteLine(p);//顯示(2,2)
這裡未裝箱的Point p 轉型為IChangeBoxedPoint,這個轉型造成對p的值進行裝箱,然後已裝箱的值上調用Change,這確實讓m_x,m_y變成了4,4,
但是,在Change返回之後,已裝箱的對象立即裝備好進行垃圾回收,所以顯示(2,2)
最後的例子中,o引用已裝箱Point要轉型為一個IChageBoxedPoint。這裡不需要進行裝箱,因為o已經是一個裝箱的Point。然後調用Change,他能正確
修改已裝箱的Point的m_x,m_y字段。接口方法允許更改一個已裝箱的Point對象中的字段。