具体类型*可能是一次性的多态性

Bob*_*orn 5 c# polymorphism idisposable

如果依赖容器或数据访问工厂可以返回可能实现的类型,IDisposable那么客户是否有责任检查并处理它?在下面的代码中,一个数据类实现IDisposable而另一个不实现.数据访问工厂可以返回任何一个.

    private static void TestPolymorphismWithDisposable()
    {
        // Here we don't know if we're getting a type that implements IDisposable, so
        // if we just do this, then we won't be disposing of our instance.
        DataAccessFactory.Resolve().Invoke();

        // Do we just have to do something like this?
        IFoo foo = DataAccessFactory.Resolve();
        foo.Invoke();
        var fooAsDisposable = foo as IDisposable;
        if (fooAsDisposable != null) { fooAsDisposable.Dispose(); }
    }
Run Code Online (Sandbox Code Playgroud)

我问的原因是,这似乎给客户端代码带来了负担,必须处理这个问题,在构建API时,如何让客户知道他们可能需要调用dispose?是否有更好的方法来处理客户端无需检查的情况IDisposable

为了完整的工作示例,以下是其他类:

public interface IFoo
{
    void Invoke();
}

public class DataAccessBaseNotDisposable : IFoo
{
    public void Invoke()
    {
        Console.WriteLine("In Invoke() in DataAccessBaseNotDisposable.");
    }
}

public class DataAccessBaseDisposable : IFoo, IDisposable
{
    public void Invoke()
    {
        Console.WriteLine("Invoke() in DataAccessBaseDisposable.");
    }

    public void Dispose()
    {
        Console.WriteLine("In Dispose() in DataAccessBaseDisposable.");
    }
}

public static class DataAccessFactory
{
    public static IFoo Resolve()
    {
        return new DataAccessBaseDisposable();
        //return new DataAccessBaseNotDisposable();
    }
}
Run Code Online (Sandbox Code Playgroud)

joh*_*rdy 3

编辑:最好的解决方案是始终返回 IDisposable 对象,即使不需要处置该对象。这样,框架用户就不必一直检查 IDisposable。

你的框架看起来像这样:

public interface IFoo : IDisposable
{
    void Invoke();
}

public class DataAccessBase : IFoo
{
    public void Invoke()
    {
        Console.WriteLine("In Invoke() in DataAccessBase.");
    }

    public void Dispose()
    {
        Console.WriteLine("In Dispose() in DataAccessBase.");
    }
}

public static class DataAccessFactory
{
    public static IFoo Resolve()
    {
        return new DataAccessBase();
    }
}
Run Code Online (Sandbox Code Playgroud)

它的消耗正如你所期望的:

private static void TestPolymorphismWithDisposable()
{
    using(IFoo foo = DataAccessFactory.Resolve())
    {
        foo.Invoke();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您是用户,并且您遇到的结果可能会或可能不会实现 IDisposable,则您需要按如下方式使用它:

private static void TestPolymorphismWithDisposable()
{
    IFoo foo = DataAccessFactory.Resolve();

    using(foo as IDisposable)
    {
        foo.Invoke(); //This is always executed regardless of whether IDisposable is implemented

        //Dispose is called if IDisposable was implemented
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅以下问题:Using statements with a null objectUsing 'as IDisposable' in a using block