1、通过泛型
//obj是一个int类型的值类型,在new Test的时候传进去的obj是就会装箱成引用类型,以为Test类是引用类型
int obj = 2;
Test test = new Test(obj);
//通过泛型这里obj传进去的就是值类型,就不需要装箱了
Test<int> test = new Test<int>(obj);
第一段代码中会发生装箱,因为int
类型的值被传递给一个引用类型的构造函数。而第二段代码中不会发生装箱,因为Test<int>
是一个泛型类,它直接使用int
作为类型参数,而不需要将其转换为引用类型。
2、使用泛型List,不用ArrayList
List是泛型的不会发生装箱,而ArrayList
存储的是对象的引用,当你存储值类型时,会发生装箱。
// 创建一个ArrayList实例
ArrayList arrayList = new ArrayList();
// ArrayList可以存储任何类型的对象,因此不需要指定类型参数
arrayList.Add(10); // 自动装箱为object
// 使用泛型 List<int> 存储整数
List<int> intList = new List<int>();
intList.Add(10);//不会装箱
在上述示例中,我们使用了 List<int>
来存储整数,使用 List<string>
来存储字符串。泛型的 List<T>
提供了类型安全,避免了像 ArrayList
那样可能出现的类型不匹配问题。
3、警惕隐式类型转换--使用合理的方法进行类型转换(通过查阅资料和反编译实现代码,并没有装箱的,不知道是不是现在已经优化了,以前有这个问题)。
一些情况下我们很容易忽略了一些值类型隐式换为System.Object的操作。1是值类型,s是引用类型,这个”s +1”操作,虽然没有显式的类型转换,但是确实发生了装箱的操作。这个说法经过反编译后的代码和第二个例子是一样的,不知道是不是现在已经优化了,以前有这个问题。
string s="测试";
s=s+1;
1使用ToString()就不会装箱了,这个说法是正确的,因为int自身是有ToString()方法,不是调用的object的ToString()。
string s="测试";
s=s+1.ToString();