To achieve something similar in a reusable fashion, you can create a static helper method:
public static class Disposable
{
public static void DisposeIfNotNull(ref IDisposable disposableObject)
{
if (disposableObject != null)
{
disposableObject.Dispose();
disposableObject = null;
}
}
}
You can call the method like this:
Disposable.DisposeIfNotNull(ref someDisposableObject);
This is not going to work for properties since you cannot pass a property to a ref
parameter.
To make it work for Properties as well, you can use expressions:
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;
}
}
This method works with variables, fields and properties. It disposes any disposable object, but only sets it to null if it is writable.
You can dispose anything in the same way, as illustrated by the method Foo.CleanUp
in the following example:
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);
}
}