大众处理,更好的方式?

时间:2013-08-15 13:43:36

标签: c# dispose

因此,当我关闭表单时,我正在处理许多对象。即使它可能会自动处理它。但我仍然倾向于遵循处理中的“规则”,希望它会坚持并帮助防止错误。

所以这就是我目前处理的方式,它有效。

        if (connect == true)
        {
            Waloop.Dispose();
            connect = false;
            UninitializeCall();
            DropCall();

        }
        if (KeySend.Checked || KeyReceive.Checked)
        {
            m_mouseListener.Dispose();
            k_listener.Dispose();

        }
        if (NAudio.Wave.AsioOut.isSupported())
        {
            Aut.Dispose();
        }

        if (Wasout != null)
        {
            Wasout.Dispose();
        }
        if (SendStream != null)
        {
            SendStream.Dispose();
        }

所以基本上,首先是如果一个博尔是真的,这意味着如果它不是那些可以忽略的,因为我认为它们并没有被制作出来。

如果有的话,其他的只是让我处理的方法。但这不是一个很好的方式,我想把它放在一个大功能中,意思是。

如果不处理则处理。或者其他的东西。 我知道他们中的许多人都有“被处置”的布尔,所以如果我可以检查每个对象,并且如果它是假的则应该可以处理。

4 个答案:

答案 0 :(得分:5)

将实现IDisposable的对象作为参数的辅助方法怎么样?

void DisposeAll(params IDisposable[] disposables)
{
  foreach (IDisposable id in disposables)
  {
    if (id != null) id.Dispose();
  }
}

如果要处理多个对象,请使用要处置的任何对象调用该方法。

this.DisposeAll(Wasout, SendStream, m_mouseListener, k_listener);

如果您想避免将其称为明确,请将它们全部存储在List<>

private List<IDisposable> _disposables;

void DisposeAll() {
  foreach(IDisposable id in _disposables) {
    if(id != null) id.Dispose();
  }
}

答案 1 :(得分:2)

您可以按照这些方针实施一个Disposer课程,为您完成这项工作:

public class Disposer
{
   private List<IDisposable> disposables = new List<IDisposable>();

   public void Register(IDisposable item)
   {
      disposables.Add(item);
   }

   public void Unregister(IDisposable item)
   {
      disposables.Remove(item);
   }

   public void DisposeAll()
   {
      foreach (IDisposable item in disposables)
      {
        item.Dispose();
      }
      disposables.Clear();
   }
}

然后,您可以使用以下内容代替主要类中的丑陋代码:

public class Main
{
   //member field
   private Disposer m_disposer;

   //constructor
   public Main()
   {
       ....
       m_disposer = new Disposer();
       //register any available disposables
       disposer.Register(m_mouseListener);
       disposer.Register(k_listener);
   }

   ...

   public bool Connect()
   {
       ...
       if (isConnected)
       {
           Waloop = ...
           Wasout = ...
           // register additional disposables as they are created
           disposer.Register(Waloop);
           disposer.Register(Wasout);
       }
   }

   ...

   public void Close()
   {
     //disposal
     disposer.DisposeAll();
   }
}

答案 2 :(得分:1)

我建议您使用using statement。因此,使用您的代码,它看起来像这样:

  using (WaloopClass Waloop = new WaloopClass())
  {
        // Some other code here I know nothing about.

        connect = false; // Testing the current value of connect is redundant.
        UninitializeCall();
        DropCall();
  }

注意现在没有必要显式Dispose Waloop,因为它会在using语句的末尾自动发生。

这将有助于构建代码,并使Waloop的范围更加清晰。

答案 3 :(得分:1)

我认为你要解决的唯一问题是如何以更好的方式编写以下内容:

if (Wasout != null)
    Wasout.Dispose();
if (SendStream != null)
    SendStream.Dispose();

using关键字已经实现了很多逻辑。在为您致电Dispose()之前using checks that the variable is not null。此外,using保证抛出的异常(per {Wasout.Dispose())不会中断在其他列出的对象(例如Dispose())上调用SendStream的尝试。似乎using旨在允许基于范围规则管理资源:使用using作为写o.Dispose()的替代方式可能被视为滥用该语言。但是,using行为的好处和它所带来的简洁性非常有价值。因此,我建议将“if (o != null) o.Dispose()”的大量静态编写批次替换为“空”using

using (
    IDisposable _Wasout = Wasout,
    _SendStream = SendStream)
{}

请注意,调用Dispose()的顺序与using块中列出对象的方式相反。这遵循以与实例化顺序相反的方式清理对象的模式。 (想法是稍后实例化的对象可能会引用先前实例化的对象。例如,如果您使用梯子攀爬房屋,您可能需要保持梯子,以便您可以在之前爬回放弃它 - 梯子首先被实例化并最后清理。嗯,类比......但是,基本上,上面是shorthand for nested using。不同的对象可以被砸到同一个using块用using来表示IDisposable

dotnetfiddle of using managing exceptions.