Wenn der Code wiederholtes Boxen durch den Compiler verursacht, können Sie ihn in manuelles Boxen ändern, um die Ausführung des Codes zu beschleunigen:
//手动装箱 Int32 v = 5; //由于string.Format的参数是object类型,所以这里会造成三次装箱。 Console.WriteLine(string.Format("{0},{1},{2}", v, v, v)); //修改一下,当然这只是一个小技巧,比如程序中对同一个值的同一个操作执行多次, //应该都是要先执行一次,然后再使用的。 Object o = v;//装箱一次 Console.WriteLine(string.Format("{0},{1},{2}", o, o, o));
Durch das vorherige Codesegment gehen wir Beim Schreiben eines Programms lässt sich leicht feststellen, wann ein Werttyp eingerahmt werden muss. Es ist nichts weiter als Boxen, wenn Sie einen Verweis auf einen Werttyp erhalten möchten. Der Unterschied zwischen Werttypen und Referenztypen ist auch hier deutlich zu erkennen:
1. Werttypen weisen keinen Speicherplatz im verwalteten Heap zu, während Referenztypen den in der Klasse angegebenen Speicherplatz nach der Instanziierung zuweisen.
2. Werttypen haben keine zusätzlichen Mitglieder von Objekten auf dem Heap, nämlich „Typobjektzeiger“ und „Synchronisationsindex“.
Unboxed-Werttypen verfügen nicht über synchronisierte Indizes. Daher können Sie keine Methoden der Klasse verwenden, in der sich der Typ befindet (z. B. Sperren), um mehreren Threads die Synchronisierung des Zugriffs auf diese Instanz zu ermöglichen.
Obwohl Werttypen ohne Box keine Typobjektzeiger haben, können vom Typ geerbte oder überschriebene virtuelle Methoden dennoch aufgerufen werden, wie z. B. Equals, GetHashCode und ToString. Wenn ein Werttyp eine dieser virtuellen Methoden überschreibt, kann die CLR diese Methode nicht virtuell aufrufen, da der Werttyp implizit versiegelt ist und kein Typ davon abgeleitet werden kann. Darüber hinaus sind Werttypinstanzen, die zum Aufrufen virtueller Methoden verwendet werden, nicht eingerahmt. Wenn die überschriebene virtuelle Methode die Methodenimplementierung in der Basisklasse aufruft, wird die Werttypinstanz beim Aufruf der Basisklassenimplementierung eingerahmt. Da diese Methoden durch System.Object definiert werden, erwarten diese Methoden, dass das Argument this ein Zeiger auf ein Objekt auf dem Heap ist.
Darüber hinaus erfordert die Umwandlung einer nicht geboxten Instanz eines Werttyps in eine der Schnittstellen des Typs, dass die Instanz geboxt ist. Denn die Schnittstellenvariable muss einen Verweis auf ein Objekt auf dem Heap enthalten. Schauen Sie sich den folgenden Code an:
class Program { static void Main(string[] args) { Point p1 = new Point(10, 10); Point p2 = new Point(20, 20); //调用ToString不装箱,这里ToString是一个虚方法 Console.WriteLine(p1.ToString()); //GetType是一个非虚方法,p1要装箱 Console.WriteLine(p1.GetType()); //这里调用的是public int CompareTo(Point p) //p2不会装箱 Console.WriteLine(p1.CompareTo(p2)); //p1要装箱,这就是将未装箱的值类型转为类型的某个接口时 IComparable c = p1; Console.WriteLine(c.GetType()); //这里调用的是public Int32 CompareTo(Object o), //而且c本来就是一个引用,因此不装箱了 Console.WriteLine(p1.CompareTo(c)); //这里调用的是c的CompareTo方法,参数是object型的 //所以要对p2装箱 Console.WriteLine(c.CompareTo(p2)); //对c拆箱,并复制值到p2中 p2 = (Point)c; Console.WriteLine(p2.ToString()); } } internal struct Point : IComparable { private Int32 x; private Int32 y; public Point(Int32 x, Int32 y) { this.x = x; this.y = y; } public override string ToString() { return string.Format("{0},{1}", x, y);//这里装箱两次,不知道有没好办法。 } public int CompareTo(Point p) { return Math.Sign(Math.Sqrt(x * x + y * y) - Math.Sqrt(p.x * p.x + p.y * p.y)); } public Int32 CompareTo(Object o) { if (GetType() != o.GetType()) { throw new ArgumentException("o is not Point."); } return CompareTo((Point)o); } }
Das Obige ist das Grundwissen von C# (19) Boxing und Unboxing von Werttypen (2) Für weitere verwandte Inhalte achten Sie bitte auf PHP Chinesische Website (www.php.cn)!