今天在調試修改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);
}
}
}