簡體   English   中英

通用處理並在C#中設置為null

[英]Generic dispose and set to null in c#

我發現自己在課堂上為數據庫對象這樣做:

if (Db != null)
{
    Db.Dispose();
    Db = null;
}

幾個問題 ...

  1. 我是否應該將Db對象設計為具有較短的壽命,並因此能夠將其放入using塊中?
  2. 有沒有一種通用的方式來執行此操作,而不是每次處理某些東西時都寫3行?

除了這些事情,我對是否有可能實現類似的目標很感興趣:

static void SafeDispose(ref IDisposable obj)
{
    if (obj != null)
    {
        obj.Dispose();
        obj = null;
    }
}
  1. 大概是這樣。 沒有看到更多的課程,就無法確定。 但根據經驗,我會盡量避免使用可拋棄的字段或屬性(我假設是這樣,因為如果它是局部變量,則可以使用using )。 除非您的類也是IDisposable並且您在Dispose()方法中對其進行清理,否則很難對其進行管理。
  2. 您可以將這些行重構為它們自己的方法,例如DisposeDb()
    public static void MyDispose(ref DbContext db)
    {
        if (db != null)
        {
            db.Dispose();
            db = null;
        }
    }

或類似的東西卡在某個班級的某個地方。

  1. 有沒有一種通用的方式來執行此操作,而不是每次處理某些東西時都寫3行?

要以可重用的方式實現類似的目的,可以創建一個靜態幫助器方法:

public static class Disposable
{
    public static void Dispose(ref IDisposable obj)
    {
        if (obj!= null)
        {
            obj.Dispose();
            obj = null;
        }
    }
}

您可以這樣調用方法:

Disposable.Dispose(ref someDisposableObject);

這不適用於屬性,因為您無法將屬性傳遞給ref參數。 要使其也適用於“屬性”,可以使用表達式:

public static class Disposable
{
    public static void Dispose(Expression<Func<IDisposable>> expression)
    {
        var obj = expression.Compile().Invoke();
        if (obj == null)
            return;

        obj.Dispose();

        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null || !IsMemberWritable(memberExpression.Member))
            return;

        var nullExpression = Expression.Constant(null, memberExpression.Type);
        var assignExpression = Expression.Assign(memberExpression, nullExpression);
        var lambdaExpression = Expression.Lambda<Action>(assignExpression);

        var action = lambdaExpression.Compile();
        action.Invoke();
    }

    private static bool IsMemberWritable(MemberInfo memberInfo)
    {
        var fieldInfo = memberInfo as FieldInfo;
        if (fieldInfo != null)
            return !fieldInfo.IsInitOnly && !fieldInfo.IsLiteral;

        var propertyInfo = memberInfo as PropertyInfo;
        if (propertyInfo != null)
            return propertyInfo.CanWrite;

        return true;
    }
}

此方法適用於變量,字段和屬性。 它處理任何一次性對象,但僅在可寫時將其設置為null。

您可以用相同的方式處置任何東西,如以下示例中的Foo.CleanUp方法所示:

public class Bar : IDisposable
{
    // ...
}

public class Foo
{
    private Bar _barField = new Bar();

    public Bar BarProperty { get; set; } = new Bar();

    public void CleanUp()
    {
        Disposable.Dispose(() => _barField);
        Disposable.Dispose(() => BarProperty);

        var barVariable = new Bar();
        Disposable.Dispose(() => barVariable);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM