处置封闭有一种奇怪的行为

时间:2015-10-26 14:02:30

标签: c# closures idisposable

我有一个像这样的一次性课程:

public class Person:IDisposable
{
    public string Name{get;set;}

    public void Dispose()
    {}
}

这里有一组扩展方法,如果调用者为null,则返回默认值:

static class Extensions
{

    public class Option<T>
    {
        private readonly Func<T> _resultGetter;

        public bool HasValue { get; }

        public Option(Func<T> resultGetter, bool hasValue)
        {
            _resultGetter = resultGetter;
            HasValue = hasValue;
        }

        public T Value => _resultGetter();
    }

    public static Option<TResult> SafeGetter<T, TResult>(this T self, Func<T, TResult> getter, Func<TResult> defaultGetter = null) where T : class
    {
        defaultGetter = defaultGetter ?? (() => default(TResult));
        return new Option<TResult>(self == null ? defaultGetter :()=> getter(self),self!=null);
    }
}

正如您所看到的,SafeGetter方法返回一个Option对象,该对象具有一个带有self参数作为闭包的getter函数。

所以为了在对象被处理后测试getter函数,我写了一个像这样的测试:

public void SafeGetterDisposableTest()
{
    Extensions.Option<string> nameGetter; 
    using (var john = new Person { Name = "John" })
    {
        nameGetter = john.SafeGetter(x => x.Name);
    }
    Console.WriteLine(nameGetter.Value);
}

你可以看到我有了Option对象并在放置了john之后调用它。我以为我会得到一个例外但令我惊讶的是测试工作正常。 为什么会这样?这段代码是否以某种方式引入内存泄漏?

2 个答案:

答案 0 :(得分:2)

  

我以为我会得到一个例外,但令我惊讶的是,测试是   工作

仅仅通过实施ObjectDisposedException,您就不会收到IDisposable(或任何其他例外)。您的Dispose方法为空,即使在您的using语句调用后,也无法更改对象。如果在对象被处理后更改它以在getter中抛出异常,则会出现异常。否则,什么都不会发生。

答案 1 :(得分:1)

约定实现了IDisposable个对象,以便在他们的成员被处置后访问时,他们会抛出异常。这不是语言的行为。如果您的一次性物品实际上有一个正在使用的非管理资源,然后进行清理,那么即使您没有明确地投掷,大概在您处置后执行的操作也无法正常工作,因此约定。