给出以下扩展方法:
public void DisposeIfNotNull(this IDisposable disposableObject)
{
if (disposableObject != null) {
disposableObject.Dispose();
disposableObject = null;
}
}
任何人都可以解释为什么以下行没有任何效果:disposableObject = null;
?
答案 0 :(得分:6)
因为您只将本地引用设置为null - 而不是您传入的引用。
如果它不是扩展名,您可以使用ref
关键字,但这与扩展参数不兼容。
答案 1 :(得分:0)
要以可重用的方式实现类似的功能,您可以创建一个静态辅助方法:
public static class Disposable
{
public static void DisposeIfNotNull(ref IDisposable disposableObject)
{
if (disposableObject != null)
{
disposableObject.Dispose();
disposableObject = null;
}
}
}
你可以这样调用这个方法:
Disposable.DisposeIfNotNull(ref someDisposableObject);
这不适用于属性,因为您无法将属性传递给ref
参数。
为了使它也适用于Properties,您可以使用表达式:
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);
}
}