c#基础系列1---值类型和引用类型 (2)

所以装箱是比较耗费性能的,还有可能引发一次GC操作,而拆箱只是一个获取指针的过程耗费资源要比装箱小的多。注意:一个对象拆箱之后只能还原为原先未装箱之前的类型,例如:你不能把int32类型装箱后还原为int16类型。 所以面试的时候可以和面试官装B一下了~~

image

测试例子 值类型引用类型分别初始化N次消耗的时间,代码如下 static void Main(string[] args) { Console.WriteLine("test start"); int totalCount = 10000000; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < totalCount; i++) { TestRef temp = new TestRef() { Id = i, Name = "test" }; } sw.Stop(); Console.WriteLine($"引用类型耗时:{sw.ElapsedMilliseconds}"); sw.Reset(); sw.Start(); for (int i = 0; i < totalCount; i++) { TestVal temp = new TestVal() { Id = i, Name = "test" }; } sw.Stop(); Console.WriteLine($"值类型耗时:{sw.ElapsedMilliseconds}"); Console.Read(); } class TestRef { public int Id { get; set; } public string Name { get; set; } } struct TestVal { public int Id { get; set; } public string Name { get; set; } }

运行结果:

引用类型耗时:205 值类型耗时:152

可见初始化速度值类型是优于引用类型的,也可能是引用类型引发了GC导致。

作为方法参数传递,代码如下: static void Main(string[] args) { Console.WriteLine("test start"); long totalCount = 1000000000; Stopwatch sw = new Stopwatch(); sw.Start(); TestRef tempRef = new TestRef() { Id = 1, Name = "test" , Name2="r3rewfdsafdsa", Name3="fsrewfdsafdsafdsa", Name4="fdafdasfdsafdsa", Name5="432tretsfds", Name6="fdsafdasfdasfd" }; for (int i = 0; i < totalCount; i++) { TestR(tempRef); } sw.Stop(); Console.WriteLine($"引用类型耗时:{sw.ElapsedMilliseconds}"); sw.Reset(); sw.Start(); TestVal tempVal = new TestVal() { Id = 1, Name = "test", Name2 = "r3rewfdsafdsa", Name3 = "fsrewfdsafdsafdsa", Name4 = "fdafdasfdsafdsa", Name5 = "432tretsfds", Name6 = "fdsafdasfdasfd" }; for (int i = 0; i < totalCount; i++) { TestV(tempVal); } sw.Stop(); Console.WriteLine($"值类型耗时:{sw.ElapsedMilliseconds}"); Console.Read(); } static void TestR(TestRef r) { return; } static void TestV(TestVal v) { return; } class TestRef { public int Id { get; set; } public string Name { get; set; } public string Name2 { get; set; } public string Name3 { get; set; } public string Name4 { get; set; } public string Name5 { get; set; } public string Name6 { get; set; } } struct TestVal { public int Id { get; set; } public string Name { get; set; } public string Name2 { get; set; } public string Name3 { get; set; } public string Name4 { get; set; } public string Name5 { get; set; } public string Name6 { get; set; } }

运行结果:

引用类型耗时:4437 值类型耗时:5226

可见在普通情况下,作为参数值类型和引用类型用时差距不大,但是,如果值类型的实例属性比较多的情况下差距降进一步拉大。

非正式环境测试用例,结果仅供参考 应用场景

不止是面试的时候经常问应用场景这个问题,就是自己平时写程序也应该清楚。程序设计选择的时候大部分场景都是用引用类型,但是如果你满足下列条件,值类型可能更适用:

类型不会派生出任何其它类型,也就是说不会有被继承的可能

类型不需要继承其他类型

类型的实例比较小,并且不会被作为方法参数,不会被频繁赋值

你永远不会用到类型释放时候的通知,因为引用类型利用析构函数可以利用其他手段可以得到释放时候的通知。

如果你的类型实例不会发生值的改变或者可以认为是readonly性质的,值类型或许是首选。

其他

所有的值类型都从System.ValueType 派生,System.ValueType继承System.Object,但是System.ValueType 重写了Equals 和GetHashCode 方法,其实在这里才是真正和引用类型的分割线。

因为值类型有装箱拆箱的操作,所以像ArrayList这样的集合性能是非常令人担忧的。所以c# 2.0 出现了泛型 例如:List .....来保证了类型安全,同时又避免了拆箱装箱,因为不是我定义的类型 ,你TMD根本连编译器那一关都过不了 哈哈哈~~~~

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyxjys.html