zoukankan      html  css  js  c++  java
  • c#:使用using关键字自动释放资源未必一定就会有明显好处

    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还是推荐使用的!我的用意在于大家对于一些具体问题要具体分析,不可纯教条主义,一味迷信某些主流的观点)

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
     
  • 相关阅读:
    Java Web开发 之VO、PO、DTO等收集
    Hive的安装与使用
    各种默认回车提交表单
    A/B Problem
    A+B Problem II
    A+B Problem IV
    关于521
    劝你别做
    无主之地1
    A+B Problem(V)
  • 原文地址:https://www.cnblogs.com/wangfuyou/p/8018499.html
Copyright © 2011-2022 走看看