Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得
在設計泛型類別時,需考慮輸入的類別是否有實作 IDisposable;若沒有適當處理外部資源,會提高記憶體洩漏的風險。此節提供幾種設計方式,避免上述情況發生。
1. 當初始化輸入類別職責在泛型類別時,使用 using 區塊自動釋放資源。
public interface IEngine
{
void doWork( );
}
public class EngineDriveOne<T> where T : IEngine, new()
{
// May leaks resource, because we couldn't confirm whether driver was
// implemented IDisposabe or not.
public void getThingsDone( )
{
T driver = new T( );
driver.doWork( );
}
public void getThingsDone2( )
{
T driver = new T( );
using ( driver as IDisposable )
driver.doWork( );
}
}
using 區塊是 C# 的語法糖。當離開 using 區塊時,若轉型成功則執行 Dispose;失敗則不執行。
2. 當輸入類別為泛型類別的類別成員時,讓泛型類別實作 IDisposable。
public sealed class EngineDriverTwo<T> : IDisposable
where T : IEngine, new()
{
private Lazy<T> _driver = new Lazy<T>( ( ) => new T( ) );
public void getThingsDone( ) =>
_driver.Value.doWork( );
public void Dispose( )
{
if ( _driver.IsValueCreated )
{
var resource = _driver.Value as IDisposable;
resource?.Dispose( );
}
}
}
Note:類別加上了 sealed 修飾字,如此一來就不會有子類別記憶體洩漏的問題(無法被繼承)。
3. 利用 Dependecy Injection 原則,將物件初始化與釋放資源的職責交給外部。
public sealed class EngineDriverThree<T> where T : IEngine
{
private T _driver;
// Dependency Injection
public EngineDriverThree( T driver )
{
_driver = driver;
}
public void getThingsDone( ) =>
_driver.doWork( );
}
結論:
1. 設計泛型類別時需考慮輸入類別的資源釋放。
2. 資源釋放的處理方式不只一種,視情況選擇最適合的方式。
1. 設計泛型類別時需考慮輸入類別的資源釋放。
2. 資源釋放的處理方式不只一種,視情況選擇最適合的方式。