If the code causes repeated packaging by the compiler, You can manually bind it to make code execution faster. See the following code:
[Csharp]
// Manual packing
Int32 v = 5;
// Because the string. Format parameter is of the object type, it will cause three times of packing.
Console. WriteLine (string. Format ("{0}, {1}, {2}", v ));
// Modify it. Of course, this is only a small trick. For example, the same operation of the same value is executed multiple times in a program,
// It should be executed once before use.
Object o = v; // boxed once
Console. WriteLine (string. Format ("{0}, {1}, {2}", o ));
// Manual packing
Int32 v = 5;
// Because the string. Format parameter is of the object type, it will cause three times of packing.
Console. WriteLine (string. Format ("{0}, {1}, {2}", v ));
// Modify it. Of course, this is only a small trick. For example, the same operation of the same value is executed multiple times in a program,
// It should be executed once before use.
Object o = v; // boxed once
Console. WriteLine (string. Format ("{0}, {1}, {2}", o ));
Through the previous code segment, we can easily determine when the value type is to be boxed when writing a program. It is nothing more than packing when you want to get a reference of the value type. Here we can clearly see the difference between the value type and the reference type:
1. The value type does not allocate space in the managed heap. after instantiation, the reference type allocates space for the members specified in the class on the stack.
2. The value type does not have any additional member of the object on the stack, that is, "type Object Pointer" and "Synchronous Index ".
The unboxed value type does not have a Synchronous Index. Therefore, you cannot use the method (such as lock) of this type to allow multiple threads to synchronously access this instance.
Although unboxed value types do not have type object pointers, you can still use virtual methods inherited or overwritten by types, such as Equals, GetHashCode, and ToString. If the value type overrides any of the virtual methods, the CLR can call this method without any virtual means, because the value type is implicitly sealed and no type can be derived from it. In addition, value-type instances used to call virtual methods are not boxed. If the virtual method to be rewritten needs to call the implementation of the method in the base class, the value type instance is boxed when the base class is called. Because these methods are defined by System. Object, these methods expect this real parameter to be a pointer to an Object on the stack.
In addition, to convert an unboxed instance of the value type to an interface of the type, the instance is required to be packed. Because the interface variables must contain references to an object on the stack. See the following code:
[Csharp]
Class Program
{
Static void Main (string [] args)
{
Point p1 = new Point (10, 10 );
Point p2 = new Point (20, 20 );
// Call ToString without packing. Here ToString is a virtual method.
Console. WriteLine (p1.ToString ());
// GetType is a non-virtual method, and p1 needs to be packed
Console. WriteLine (p1.GetType ());
// Public int CompareTo (Point p) is called here)
// P2 will not be packed
Console. WriteLine (p1.CompareTo (p2 ));
// When p1 needs to be boxed, this is an interface that converts unboxed value types into types.
IComparable c = p1;
Console. WriteLine (c. GetType ());
// Public Int32 CompareTo (Object o) is called here ),
// And cben is a reference, so it is not packed
Console. WriteLine (p1.CompareTo (c ));
// The CompareTo method of c is called here, and the parameter is object-type
// Therefore, bind the p2
Console. WriteLine (c. CompareTo (p2 ));
// Unpack c and copy the value to 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); // It is packed twice. I don't know if there is a good solution.
}
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 );
}
}