C#之装箱和拆箱

在实际编码过程中,有时候会出现装箱和拆箱操作。下面就类分别认识一下:

需要注意的是,类型转换和这个是不同的。Convert方法并没有发生装箱和拆箱操作,而是类型转换,包括int.parse等等。

装箱,是把值类型拷贝了一个副本放在堆内存中。

拆箱,在引用类型直接找到值类型存储的位置(Person对象是引用类型,但其Age属性是值类型,也存储在堆内存中),实际上我们往往拆箱后会用一个值类型变量接收它。

例1:

             int n = ;
Console.WriteLine(n);
object o = n;//一次装箱
Console.WriteLine((int)o);
Console.WriteLine(o);//这里输出的是字符串"10",相当于Console.WriteLine(o.ToString());

上面的代码中,第2句话并没有发生装箱,因为Console.WriteLine()方法有一个int类型重载;第3句话发生一次装箱;而第4句话(int)o发生一次拆箱,拆箱后的值被其values接收,如果没有Console.WriteLine()方法有一个int类型重载的话,会马上再次装箱,因为这个重载,没有发生装箱;最后1句话,输出的是字符串"10",相当于Console.WriteLine(o.ToString())。所以在判断一句话是否发生装箱和拆箱要结合构造函数来看。

例2:

             int n = ;

             IComparable com = n;

             int m = (int)com;

             Console.WriteLine(m);

上面的代码中,第二句话发生了装箱,第三句话发生了拆箱,因为int类型实现了IComparable接口。

例3:

             int d = ;
object o = d; //装箱 //装箱时使用什么类型,拆箱时也必须使用同样的类型。否则报异常
double d1 = (double)o; //拆箱
Console.WriteLine(d1);

例3中,编译会报错,以为在第2句话装箱前是int类型,而拆箱时确是double。需要注意的是,装箱前是什么类型,拆箱后也必须是什么类型,否则会报错

例4:

            int n = ;
M1(n); string x = "a";
double d1 = ;
string y = "b";
int n1 = ;
string z = "c";
string full = x + d1 + y + n1 + z;
Console.WriteLine(full); //定义函数如下:
static void M1(double d)
{
Console.WriteLine(d);
} static void M1(object o)
{
Console.WriteLine(o);
}

上面的代码到底发生了几次装箱和拆箱呢?首先看M1()方法,经反编译得知M1((double) n);由此可见,M1()方法并没有去找object类型的重载,而是找了与之相近的double类型重载,所以没有发生装箱。第9句话经反编译得知Console.WriteLine(string.Concat(new object[] { x, d1, y, n1, z }));它将double类型变量d1和int类型变量n1装箱成object类型。所以上面的代码只发生了2次装箱。

装箱和拆箱带来的性能影响:

日常编码中应避免装箱和拆箱,因为他们会带来性能的损耗。看下面的代码:

             ArrayList aList = new ArrayList();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = ; i < ; i++)
{
aList.Add(i); //Add方法每添加一次发生一次装箱
}
sw.Stop();
Console.WriteLine("用时:"+sw.Elapsed);

运行结果:aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAAAdCAIAAAB36yScAAAIWklEQVR4nO1a23LbOAyFZNnp7f8/JnVkiRIpyWkznb41jRw7kya2LrbTmb7vw1mjCGk5dbZb72aMB4WkQRAED0GADFVVVdf1YrGYz+d1XTdNU1UVvlVVzefzpmnwrapqsVjc3d0tFou6rufzORhYAqiu67u7u/mGWDIK4IGoI70YIsClrmtgqG1bVJumYVS1bcstKCyXy7qu0c7duYW/KNR1vVwuJUCbI70sIoCAl/bh4WGxWLRtC6Asl8u2bZumQaFt29VqhTK+q9Wqbdv1eo321WqFMgrr9Xq5XC4Wix8/flRV9f3796qqVkd6cfS3N2J/02y8BWML55Gs3t/fN03DhyC7H/ZM/EUX4BItq9UKR2R9pBdEhD9N0wBWk8nk8vLy8vLy5ubm+vr6+vp6Op1OJpPb29vJZDKbzabTaVmWt7e3ZVmCoSzL6XR6dXVVlmVZlpPJBD9NJpPpdAqG2WxWluXNzc3Xr19nsxnEHunFEFVVdX9/v1wu4ZOurq7oXyCl1L8h9kj/Fao3pxUim7Is0W6MOT8/11qPx+OiKIwx4/E4y7IkSdI0TdPU87xer+f7/mAw8H3f8zzP87pG0VqDn4i8I704ouZxLvblyxcsfBiGEgej0Wh3NY7jKIqUUnEcuzCKoug5GD/S/4VwhcPp2HQ6RXuWZSh4nkdE4/FY9rKqzExERVG4o3z48KFLgZ+I3pDv+5IhCAKpCRHBq+Erqd/vd40i+Q8lZ995MT84vW5nTxszdv3UVbVU4l/d9ieoC0bwHyzOCm6MMW715OSEiM7Pz4moKIowDLXWSZIopdI01VoDTIPBAPaVZxwPhII1Da11FEVxHENgr9dDlzRNz87O0jRNksQY0+v1+v0+xEKCtbRZlh1Wzq/PK4qiKIogKggCIElrHcexMWY0Gg0GAwhUSiVJorVGATs8CILBYIBe1mJ5nqe1DsMwTdM4jlkOdEMjghbI4Snsoi4YISR6//59URRKqYuLC2MMFI2iCIDAwJ7nZVnGGGelpcks77WVEGCRs/kwLhG9evWKiKAV1hJnK/jzPLcOYoCV1ciy7LBy9p2X1Y4FRnet9enpKeSkaco2d9c7SZI8z+W4aZpmWcYIOz095V48Ncsv7naERN0wkhaBNlKc1hoFGBeKwtwW9kE46Xgl5AZlRd3TjaedJAnaUVZK9Xq9OI6hFdRDO58j2J2sJ/ryJvvzcvadF9IXDK2UOjk5iaKI5SulsJODIMjzXCnleR4W6+3bt0R0cnKSJAlcF1YHFAQBPB/WSynFO3w8HkMOtIWXCoLgaQxRN4wuLi4k2+fPn6W4T58+yV+11gBymqaY3rt37yQDsMW4YV0lD1ctMMHnE1GSJEVRIJAnojzP0R7HcZ7ncMVEhPkj2JfLr5SCGgeR84x5weuHYYgAo9frsXvI85yzHPY3rkl935fgY8LpSURZlg2HQ/ZwEnDkBG27qAtGZ2dnJLwRqkwwEI8Es8JeHG67cbd0P11BnIsw9rQY9PT0FHbRWsOUGAhBiSVfyjHGIIs8iJxnzAvV4XAIVMmjgE83VBGT4S6GiPr9PuJU2oRf0sK8pojweJpxHGdZFsfxaDQyxmDiu7ONn7QjU8vzfDgcFkURxzGujhAbjUYjeEKO6iWKP378SJtwm/cBcCb9Dc/ZCq7lPEFRFBljhsMhlgcBJoSHYRiGIUaBntS9h7AvDyhnr3lxOzseyMEyo4w1lrmV5TiJaDQauWlyEASIcaUcxF5gSJJEOo7nx0ZWiIP8q6sqmXkL4miX9wUcY/q+zye0RexvmbDbeN+wpZBuIIz1PE9GmiSSINlijDmUnH3nxe1aa0YG0isS6QgTx1hKKZkVGmOkUySiIAgQitFjfMjjL0kSgNgdaDvhFhswqut6MpmgXaKBHFRJJWAyrm5997AcDz32TBaz5f8BOG9zCQ6XDh3g22WUKjVEcMqbFQY9lBygShpn97xkR/RC/k+b/cnYkvyI062VsmCEI6VLDpR3ez1B9eYBv67rtm0ZRgwUjr9IBAqcYrBFRqMRLC7vkJgfy8BdfN93FZUvKtwRBVg8DEOErniBIaI8z5ET8dIGQYBQdOseAvNB5MDxYItzVmWM2SEHyDPGeJ7X7/eNMbADgndkc3y5oJQqiiJN096GIBzODKIAWcjskgOwQnnf94Mg+CWHhHdZflO7ubkhJ70n4Y2wddgcRNTv92UQZ+0G6cxQhqW6YERO9L3H7cVjsjKjg8txxf4WOTuE7H0Z/WxaLpez2Qz/ULZer/E0y8EXJ6ucLMCv4IaDiN68eUNEr1+/ZqURr1kXTkmSoB23GrhYk/QrNpXObGv1yRfiA8p5xrwYr3zd39VRtuDCSb6oWGDqegCxeLoG3U7fvn17eHi4v79fr9dN08xmM+QFVgLFeOr1emdnZziz8LWuiGiDITZiGIboDvRY/O5BttteWwMscpzEk7vzD8vZSjJ365LjZrI7eOTad40LnP3KWHv4y7qub29vV6tV0zRt2+JQc3syMlCVqKLHmSewYiXJfP0gPdaOFXLn5s7c3VUuj7uuh5LjguDJeW1dRbeX5Takwpbye8mRajwNI8TXCI+aprm+vpZCWS7jBiRx4G2IHptYji353Rdsi9y3THwBZbhA5uFRoKEcFPzgdMt/Xg4H7FYUuFUOG4cvElkU+CHfwjQa5U+8RryT2f475OAn66JrF/E/0S4WC46NyFljy7tY8JQZDV8OWc5zd3d6vAbApQtH+WSIQd1tJ9dArro74p+Xw2/4T84L7ZLT1Ye3pWTjn6QXQdlNPLfKkSpB26dD9a7rxyMdaQ86wuhIv4GOMDrSb6AjjI70G+gIoyP9c/oLg4X52gURJ3IAAAAASUVORK5CYII=" alt="" />

我们换另一种:

             List<int> aList = new List<int>();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = ; i < ; i++)
{
aList.Add(i);
}
sw.Stop();
Console.WriteLine("用时:" + sw.Elapsed);

运行结果:aaarticlea/png;base64,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" alt="" />

由此可见,性能影响还是挺大的。

总结:

一)装箱和拆箱的判断依据:
1.发生在值类型和引用类型之间;
2.具备父子类的关系。

二)判断一句话是否发生装箱和拆箱要结合构造函数来看;

三)装箱前是什么类型,拆箱后也必须是什么类型,否则会报错;

四)写代码的过程中应尽量避免装箱和拆箱带来的性能消耗。

上一篇:Html中鼠标悬停显示二级菜单的两种方法


下一篇:Windows API 之 CreateThread、GetExitCodeThread(未完)