博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c#:使用using关键字自动释放资源未必一定就会有明显好处
阅读量:6279 次
发布时间:2019-06-22

本文共 4644 字,大约阅读时间需要 15 分钟。

public string ToXML()            {                string strXml = string.Empty;                try                {                    MemoryStream ms = new MemoryStream();                    XmlSerializer xml = new XmlSerializer(this.GetType());                    xml.Serialize(ms, this);                    byte[] arr = ms.ToArray();                    strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);                    return strXml;                }                catch                {                    return "";                }            }

象MemoryStream这类资源,应该用using包起来自动释放资源,否则会有内存泄漏问题。在using的使用上,我也同意应该使用using,但由于这类风格的代码在原项目中非常多(有一部分历史原因),如果一一修改,工作量太大,时间不允许。于是我就在内心评估:如果不改,现在这种代码的风险到底有多大?

我想很多人都知道using(Resource res = new Resrouce){},其实相当于

Resource res = new Resrouce

try{}

catch{}

finally{res.Dispose();}

对比与现有代码的区别,无非就是资源没有调用Dispose()释放,但是CLR有强大的GC(垃圾回收)机制,方法调用完成后,方法体中创建的托管资源如果不再被使用,也一并会被GC列为可回收对象,所以就算开发人员没有手动调用Dispose,其实CLR也会帮我们做这件事情,只是时机可能会晚一些而已。

于是有了下面的测试:

1.先创建一个示例用的Class

using System;    using System.Collections.Generic;    using System.Linq;    using System.Text;    using System.IO;    using System.Xml.Serialization;         namespace Model    {        public class SampleClass        {            public string Name { set; get; }                      public string ToXMLNoUsing()            {                string strXml = string.Empty;                try                {                    MemoryStream ms = new MemoryStream();                    XmlSerializer xml = new XmlSerializer(this.GetType());                    xml.Serialize(ms, this);                    byte[] arr = ms.ToArray();                    strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);                    return strXml;                }                catch                {                    return "";                }            }                 public string ToXMLWithUsing()            {                string strXml = string.Empty;                try                {                    using (MemoryStream ms = new MemoryStream())                    {                        XmlSerializer xml = new XmlSerializer(this.GetType());                        xml.Serialize(ms, this);                        byte[] arr = ms.ToArray();                        strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);                         }                    return strXml;                     }                catch                {                    return "";                }            }             }    }

这其中的ToXML为了测试方便,故意分成了二个版本(一个不用using,一个用using)

2.再创建一个Console程序(命名为WithUsing),写一段测试代码:

using System;    using System.Diagnostics;    using Model;         namespace WithUsing    {        class Program        {            static void Main(string[] args)            {                Console.WriteLine("开始折腾-WithUsing...");                Stopwatch watch = new Stopwatch();                int max = 100000;                     watch.Reset();                watch.Start();                     for (int i = 0; i < max; i++)                {                    SampleClass c = new SampleClass() { Name = i.ToString().PadLeft(1024, '0') };                    c.ToXMLWithUsing();                }                watch.Stop();                Console.WriteLine("完成,{0}次操作共耗时:{1}毫秒,平均{2}毫秒/次!", max, watch.ElapsedMilliseconds, watch.ElapsedMilliseconds /(decimal)max);                Console.ReadKey();            }        }    }

3.再创建一个Console程序(命名为NoUsing),写一段测试代码:

using System;    using System.Diagnostics;    using Model;         namespace NoUsing    {        class Program        {            static void Main(string[] args)            {                Console.WriteLine("开始折腾-NoUsing...");                Stopwatch watch = new Stopwatch();                int max = 100000;                     watch.Reset();                watch.Start();                for (int i = 0; i < max; i++)                {                    SampleClass c = new SampleClass() { Name = i.ToString().PadLeft(1024, '0') };                    c.ToXMLNoUsing();                }                     watch.Stop();                Console.WriteLine("完成,{0}次操作共耗时:{1}毫秒,平均{2}毫秒/次!", max, watch.ElapsedMilliseconds, watch.ElapsedMilliseconds / (decimal)max);                Console.ReadKey();            }        }    }

编译后,同时运行这二个程序,同时利用任务管理器观察内存使用情况:

反复多次运行比较,发现其实二者占用的内存几乎完全相同,这说明GC还是很给力的!

而且从执行时间上看,不用Using,反而更快,这也容易理解:用Using相当于每次都要调用Dispose()方法,这会带来一些系统开销;而不用Using,GC会在适当的时机批量回收资源,性能反而更好。(当然:这个结论不是要误导大家不用using,对于using还是推荐使用的!我的用意在于大家对于一些具体问题要具体分析,不可纯教条主义,一味迷信某些主流的观点)

 

 

作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
 
 
转载:
你可能感兴趣的文章
中间件
查看>>
Android SharedPreferences
查看>>
css面试题
查看>>
Vue组建通信
查看>>
用CSS画一个带阴影的三角形
查看>>
前端Vue:函数式组件
查看>>
程鑫峰:1.26特朗.普力挺美元力挽狂澜,伦敦金行情分析
查看>>
safari下video标签无法播放视频的问题
查看>>
01 iOS中UISearchBar 如何更改背景颜色,如何去掉两条黑线
查看>>
对象的继承及对象相关内容探究
查看>>
Spring: IOC容器的实现
查看>>
Serverless五大优势,成本和规模不是最重要的,这点才是
查看>>
Nginx 极简入门教程!
查看>>
iOS BLE 开发小记[4] 如何实现 CoreBluetooth 后台运行模式
查看>>
Item 23 不要在代码中使用新的原生态类型(raw type)
查看>>
为网页添加留言功能
查看>>
JavaScript—数组(17)
查看>>
Android 密钥保护和 C/S 网络传输安全理论指南
查看>>
以太坊ERC20代币合约优化版
查看>>
Why I Began
查看>>