C#中使用条件语句块

问题描述 投票:30回答:10

我有如下代码,但它是尴尬。我怎么能更好的结构吗?我必须让我的消费类实现IDisposable,并有条件地构建网络接入等级和处置它时,我做了什么?

    protected void ValidateExportDirectoryExists()
    {
        if (useNetworkAccess)
        {
            using (new Core.NetworkAccess(username, password, domain))
            {
                CheckExportDirectoryExists();
            }
        }
        else
        {
            CheckExportDirectoryExists();
        }
    }
c# idisposable using-statement
10个回答
59
投票

一种选择,这是有点讨厌,但会工作的基础上,将C#编译器调用Dispose only if the resource is non-null的事实:

protected void ValidateExportDirectoryExists()
{
    using (useNetworkAccess 
               ? new Core.NetworkAccess(username, password, domain)
               : null)
    {
        CheckExportDirectoryExists();
    }
}

另一种替代方法是写哪个返回null或NetworkAccess一个静态方法:

private Core.NetworkAccess CreateNetworkAccessIfNecessary()
{
    return useNetworkAccess
        ? new Core.NetworkAccess(username, password, domain)) : null;
}

然后:

protected void ValidateExportDirectoryExists()
{
    using (CreateNetworkAccessIfNecessary())
    {
        CheckExportDirectoryExists();
    }
}

同样,我真不知道我不喜欢原来的...这真的取决于你如何往往需要这种模式。


0
投票

使用您自己的try / finally块,执行类似的逻辑的“使用”,但只有当useNetworkAccess设置做了处置。请注意,如果useNetworkAccess可能被其他线程的影响,你应该复制其价值,并使用该副本都为创建资源和处理它。


7
投票

如果您在很多方法重复这个模式,你可以打破格局

protected void OptionalNetworkCall(Action action)
{
    if (useNetworkAccess)
    {
        using (new Core.NetworkAccess(username, password, domain))
        {
            action();
        }
    }
    else
    {
        action();
    }
}

protected void ValidateExportDirectoryExists()
{
    OptionalNetworkCall(CheckExportDirectoryExists);
}

4
投票

using语句是一种捷径,以避免“最后”块,当它使代码更易于理解,才应使用。在你的情况我会写下面的代码。它可能不会像其他一些版本的简短,但更直截了当。

protected void ValidateExportDirectoryExists()
{
    Core.NetworkAccess access = useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : null;    

    try
    {
        CheckExportDirectoryExists()
    }
    finally
    {
       if (access != null)
       {
           access.Dispose();
       }
    }
}

2
投票
protected void ValidateExportDirectoryExists()
{
      var access = useNetworkAccess
          ? new Core.NetworkAccess(username, password, domain)
            : null;

      using (access)
      {
          CheckExportDirectoryExists();
      }
}

1
投票

我不知道这是否是“更好”,但你可以使用空对象模式,并有一个“空”一次性的网络访问对象。事情是这样的:

protected void ValidateExportDirectoryExists()     
{
  using (GetNetworkAccess(username, password, domain))
  {                 
    CheckExportDirectoryExists();
  }
} 

protected IDisposable GetNetworkAccess(string username, string password, string domain)
{
  return useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : new NullNetworkAccess(username, password, domain);
}

internal class NullNetworkAccess : IDisposable
{
  internal NullNetworkAccess(string username, string password, string domain)
  {
  }

  public void Dispose()
  {
  }
}

这可能是为自己好太可爱了。

[编辑]在Jon的回答刚才看到空可以在using语句中使用。我不知道!


0
投票

使用范围,如果这个类实现IDisposible接口将只处理一个对象,是的,你需要实现Dispose方法。


0
投票

我想这确实是化妆品的问题,如果代码是如此简单。

我可以想象它怎么可能寻找其他途径,我的投票将是这个版本你现在有。


0
投票

无论是使用语句内封闭将它称为IDispoable.DisposeIDisposable接口决定。由于在MSDN上看到了using ...

提供了一个方便的语法,确保正确使用IDisposable的对象。

因此,如果你把一个自定义类型的using语句中应该通过IDisposable接口进行相应的清理其资源。


0
投票

通过让类实现IDisposable,使用“使用”的语句时,Dispose方法只调用。否则,您必须显式调用处理。

通常IDisposable的由管理内存消耗垃圾收集器的外部(例如使用非托管代码例如)对象来实现。它提供了一种方法来清理任何消耗的内存。

只要你NetworkAccess类实现了IDisposable,Dispose方法将得到尽快using语句的范围是完整的调用。如果是托管代码,那么没有必要处置。只是让垃圾收集完成其工作。

© www.soinside.com 2019 - 2024. All rights reserved.