我可以一次处理多个对象吗?

Can I dispose multiple Objects in a single go?

我有一个 class 实例,它实现了如下所示的 IDisposable 接口。

class Instance : IDisposable
{
    //something
    void Dispose()
    {
        //Disposes something
    }

}

现在在实际代码中我有几个 Instance 实例需要像下面这样在 Finally 块中处理

 finally
        {

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

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

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

        }

所以每次我想处理时,我都必须为每个对象写上面的几行。

我觉得我可以使用 'params' 关键字来减少编号。 LOC(代码行)如下所示

   static void DisposeInstance(params Instance[] instances)
    {
        for (int i = 0; i < instances.Length; i++)
        {

            if (instances[i] != null)
            {
                instances[i].Dispose();
                instances[i] = null;
            }
        }
    }

并一次性通过实例,例如,

 DisposeInstance(inst1, inst2, inst3);

但是上面的函数只会处理实例的本地副本,而不会完全处理实际对象(实例)。

所以我的问题是,是否有任何方法可以实现一次性处理对象并减少 LOC 的目标。

我还可以将 'ref' 关键字与 'params' 一起使用(我知道这会产生编译错误),但是以某种方式混合这两者以获得结果吗?

提前致谢!

您不需要将对象设置为 null,在 C# 6 中您可以使用 Null-Propagation 语法:

inst1?.Dispose();
inst2?.Dispose();
inst3?.Dispose();

这大大降低了噪音。

您可以将列表传输到您的方法

   static void DisposeInstancies(List<Instance> instances)
    {
        for (int i = 0; i < instances.Length; i++)
        {

            if (instances[i] != null)
            {
                instances[i].Dispose();
                instances[i] = null;
            }
        }
    }

所以:

DisposeInstancies(new List<Instance> {inst1, inst2, inst3});

您可以尝试使用using statement,它会自动处理对象。像这样:

using (MyClass inst1 = new MyClass())
using (MyClass1 inst2 = new MyClass1())
using (MyClass2 inst3 = new MyClass2())
{
    // code 
}  

The using statement allows the programmer to specify when objects that use resources should release them. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object's resources.

But the above function would dispose only the local copy of the Instance and do not exactly dispose the actual objects(instances).

它处理对象(或至少它调用方法 Dispose()),但它不会在调用方范围内将引用设置为 null。实际上,在 DisposeInstance 范围内,只有 引用 的复制值被设置为 null。

你真的需要将它设置为空吗?如果您的目标是避免因多次调用 Dispose() 而导致的错误,那么您应该使用布尔值来控制状态:

private bool hasBeenDisposed ; 

public void Dispose() 
{
    if (!hasBeenDisposed)
    {
        DisposeInstance(inst1, inst2, inst3);
        hasBeenDisposed = true ; 
    }
}

此外,您应该将 DisposeInstance args 更改为 IDisposable [] 以实现可重用性和可读性。

static void DisposeInstance(params IDisposable [] instances)
{
    for (int i = 0; i < instances.Length; i++)
    {

        if (instances[i] != null)
        {
            instances[i].Dispose();
            instances[i] = null;
        }
    }
}

关于处置的小事。

处理对象时清除大型内容对象的对象。您只需将要处理的对象的内容孤立起来,以便 GC 可以自由拾取它们。

如果您想要在其上实现 IDisposable 的对象中没有任何大对象或数组,那么您实际上不需要释放它。如果您需要内存中的 space 则只需将其设为 null 以强制它超出范围并进入 GC。

(这里有一个极端情况,GC 会停止你的程序进行收集,所以如果你有很多小对象,那么在你有 "time" 时处理它们是一个很好的方法,记住在处理后抑制 GC他们)

处理是开发人员做出的一种判断。在大多数情况下,您并不真正需要它,在多种情况下,它很适合处理包含较大 arrays/collections.

的对象

因此,对于您的问题,我建议您在完成 class 后进行处理,而不是等到 "scope" 结束时,或者将它们放入列表中并进行处理稍后。

Queue<IDisposable> toDispose = new Queue<IDisposable>();
private void DisposeObjects(){
    while(toDispose.Any()){
        toDispose.Dequeue()?.Dispose();
    }
}

MSDN: Dispose Pattern