今天在调试修改C#程序时候发现编译时候爆出很多Code Analysis for Managed Code Warnings 警告。
当然警告并不影响程序,有些程序员直接忽略,我个人比较较真。看到编译器有任何警告,心里总觉得
不舒服,这可能就是职业久了得的强迫症。没办法,今天就把解决的这些错误给罗列出来,方便后人查
阅。我的代码出现的主要就是资源释放问题,说到这里就得提提C#的资源回收。非托管资源,系统自己
回收,然后我们有时候会定义创建一些非托管类的资源,这个时候就得程序员自己销毁释放了。
C#每个类都代表着一种资源,资源又被分为两类。
非托管:不受CLR管理的对象,windows内核对象,如new,stream、sqlconnection、socket、COM object等;
托管:由CLR管理分配和释放的资源,即由CLR里new出来的对象。
资源的释放方式。
非托管资源:需要显式释放的,也即需要你写代码释放(经常会遇到IDisposable接口,下面有介绍)
托管资源:并不需要显式释放,但是如果引用类型本身含有非托管资源,则需要进行现实释放;
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
//执行与释放或重置非托管资源关联的应用程序定义的任务。
系统定义的接口
using System.Runtime.InteropServices;
namespace System
{
//
// 摘要:
// 提供一种用于释放非托管资源的机制。若要浏览此类型的 .NET Framework 源代码,请参阅引用源。
[ComVisible(true)]
public interface IDisposable
{
//
// 摘要:
// 执行与释放或重置非托管资源关联的应用程序定义的任务。
void Dispose();
}
}
CA1001
CA1001: Types that own disposable fields should be disposable
解决方法
看注释
// This class satisfies the rule.
public class HasDisposeMethod: IDisposable //第一要继承
{
FileStream newFile;
public HasDisposeMethod()
{
newFile = new FileStream(@"c:\temp.txt", FileMode.Open);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
newFile.Close(); //第二要重写方法
}
// free native resources
}
public void Dispose() //第三要提供接口
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
CA2202
CA2202: Do not dispose objects multiple times
解决方案
资源不能释放多次,一般在异常处理会遇到资源多次释放。
采用try finally语句块解决。
Stream stream = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(stream))
{
stream = null;
// Use the writer object...
}
}
finally
{
if(stream != null)
stream.Dispose();
}
CA2213
CA2213: Disposable fields should be disposed
解决方法
在设计器代码页面手动加入释放资源
using System;
namespace UsageLibrary
{
public class TypeB : IDisposable
{
// Assume this type has some unmanaged resources.
TypeA aFieldOfADisposableType = new TypeA();
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
// Dispose of resources held by this instance.
// Violates rule: DisposableFieldsShouldBeDisposed.
// Should call aFieldOfADisposableType.Dispose();
disposed = true;
// Suppress finalization of this disposed instance.
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}
public void Dispose()
{
if (!disposed)
{
// Dispose of resources held by this instance.
Dispose(true);
}
}
// Disposable types implement a finalizer.
~TypeB()
{
Dispose(false);
}
}
}