Effective C# 学习笔记(四十五)减少装箱拆箱行为
2011-08-06 10:35 小郝(Kaibo Hao) 阅读(591) 评论(0) 编辑 收藏 举报值类型用来存储数据,引用类型用来表现多态,而所有.net framework中的类型都继承自System.Object。这看起来有些冲突。.NET framework 用装箱和拆箱来解决两类类型间的转换。但是这种操作是十分消耗资源且影响性能的。
装箱:把一个值类型放入一个未命名的引用类型中,以使得该类型可被当作引用类型使用。
拆箱:从一个引用类型中将值类型的值Copy取出。
可以通过范型来避免装箱拆箱,但是.net中还是有许多方法是不支持范型方法的,所以这些方法的调用,在对待值类型时会引起自动的装箱拆箱行为。如下代码所示:
Console.WriteLine("A few numbers:{0}, {1}, {2}", 25, 32, 50);
上面的方法原来的参数列表是这样的Console.WriteLine(string,object[]),所以上面的25,32,50三个int的值类型对象对自动进行装箱。其实在其内部的执行方法是这样的:
private static void SampleThree()
{
object firstParm = 5;//装箱
object o = firstParm;
int i = (int)o; // unbox
string output = i.ToString();
}
避免装箱拆箱的方法应该这样写:
Console.WriteLine("A few numbers:{0}, {1}, {2}", 25.ToString(), 32.ToString(), 50.ToString());
.NET framework 的集合类型存储的System.Object的引用类型,所以对于集合类型的范型,在传入值类型的类型参数时,会产生装箱操作。而当你讲一个对象从集合中取出,你就会从集合中得到该对象的一个拷贝。但这常常会引起一个bug。看如下带代码:
public struct Person
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
// Using the Person in a collection:
var attendees = new List<Person>();
Person p = new Person { Name = "Old Name" };
attendees.Add(p);
// Try to change the name:
// Would work if Person was a reference type.
Person p2 = attendees[0];
p2.Name = "New Name";
// Writes "Old Name":
Console.WriteLine(attendees[0].ToString( ));
如上面的代码所示:Person类型是个值类型,在List<Person>类型的对象时你只修改的了该对象的一个Copy,即一个根据原对象新创建的对象,而没有修改集合中的值。这时你应该使用immutable值类型。如第20次笔记所说。
出处:http://www.cnblogs.com/haokaibo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。