c#:使用using关键字自动释放资源未必一定就会有明显好处
记录这篇文章的灵感来源来自今天下班前与同事的小小争论,我现在开发的一个项目中,有这样一段代码:
public string ToXML()
string strXml = string.Empty;
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;
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;
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();