C# 条件 using 块语句

发布于 2024-10-06 15:35:06 字数 438 浏览 7 评论 0原文

我有以下代码,但很尴尬。我怎样才能更好地构建它?我是否必须使我的消费类实现 IDisposable 并有条件地构造网络访问类并在完成后将其处置?

    protected void ValidateExportDirectoryExists()
    {
        if (useNetworkAccess)
        {
            using (new Core.NetworkAccess(username, password, domain))
            {
                CheckExportDirectoryExists();
            }
        }
        else
        {
            CheckExportDirectoryExists();
        }
    }

I have the follow code but it is awkward. How could I better structure it? Do I have to make my consuming class implement IDisposable and conditionally construct the network access class and dispose it when I am done?

    protected void ValidateExportDirectoryExists()
    {
        if (useNetworkAccess)
        {
            using (new Core.NetworkAccess(username, password, domain))
            {
                CheckExportDirectoryExists();
            }
        }
        else
        {
            CheckExportDirectoryExists();
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

芸娘子的小脾气 2024-10-13 15:35:06

一种选择虽然有点令人讨厌,但可行,基于 C# 编译器调用 Dispose 仅当资源非 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();
    }
}

同样,我仍然不确定我是否不喜欢原来的...这实际上取决于您需要此模式的频率。

One option, which is somewhat nasty but would work, based on the fact that the C# compiler calls Dispose only if the resource is non-null:

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

Another alternative would be to write a static method which returned either null or a NetworkAccess:

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

Then:

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

Again, I'm still not sure I don't prefer the original... it really depends on how often you need this pattern.

苏佲洛 2024-10-13 15:35:06

using 语句是避免“finally”块的快捷方式,并且仅应在使代码更易于理解时使用。对于你的情况,我会编写以下代码。它可能不像其他一些版本那么简短,但更直接。

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

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

The using statement is a shortcut to avoid "finally" blocks and should only be used when it makes the code easier to follow. In your case I would write the following code. It may not be as brief as some of the other versions, but is much more straight forward.

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

    try
    {
        CheckExportDirectoryExists()
    }
    finally
    {
       if (access != null)
       {
           access.Dispose();
       }
    }
}
黄昏下泛黄的笔记 2024-10-13 15:35:06

如果你在很多方法中重复这个模式,你就可以打破这个模式

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

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

If you repeat this pattern in many methods you can break out the pattern

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

protected void ValidateExportDirectoryExists()
{
    OptionalNetworkCall(CheckExportDirectoryExists);
}
情泪▽动烟 2024-10-13 15:35:06
protected void ValidateExportDirectoryExists()
{
      var access = useNetworkAccess
          ? new Core.NetworkAccess(username, password, domain)
            : null;

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

      using (access)
      {
          CheckExportDirectoryExists();
      }
}
始终不够 2024-10-13 15:35:06

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

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 的回答中看到 null 可以在 using 语句中使用。我不知道!

I don't know if it is "better", but you could use the null object pattern and have a "null" disposable network access object. Something like this:

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()
  {
  }
}

This is probably too cute for its own good.

[EDIT]
Just saw in Jon's answer that null can be used in a using statement. I had no idea!

初吻给了烟 2024-10-13 15:35:06

仅当类实现 IDisposible 接口时,使用作用域才会处置对象,因此您需要实现 dispose 方法。

using scope will only dispose a object if the class implements IDisposible interface so yes you need to implement dispose method.

两相知 2024-10-13 15:35:06

我想如果代码就这么简单的话,这确实是一个化妆品问题。

我可以想象它会是什么样子,我的投票将投给你现在拥有的这个版本。

I guess that is really a matter of cosmetics if the code is as simple as that.

I can envision how it could look the other way, and my vote will be for this version you have now.

凉栀 2024-10-13 15:35:06

无论 using 语句中包含什么内容,都会按照 IDispoable 接口的指示调用其 IDispoable.Dispose。正如在 MSDN 上看到的使用...

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

因此,如果您将自定义类型放入 using 语句中,它应该通过 IDisposable 接口适当地清理其资源。

Whatever is enclosed within the using statement will have it's IDispoable.Dispose called as dictated by the IDisposable interface. As seen on MSDN for using...

Provides a convenient syntax that
ensures the correct use of IDisposable
objects.

Therefore if you put a custom type within the using statement it should clean up its resources appropriately via the IDisposable interface.

短叹 2024-10-13 15:35:06

通过让您的类实现 IDisposable,仅在使用“using”语句时才调用 dispose 方法。否则你必须显式调用 dispose。

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

只要您的 NetworkAccess 类实现 IDisposable,一旦 using 语句的范围完成,就会调用 dispose 方法。如果它是托管代码,则无需处置它。让垃圾收集器完成它的工作即可。

By having your class implement IDisposable, the dispose method is called only when using the "using" statement. Otherwise you have to explicitly call dispose.

Typically IDisposable is implemented by objects that manage memory consumption outside of the garbage collector (like using unmanaged code for example). It provides a way to clean up any consumed memory.

So long as your NetworkAccess class implements IDisposable, the dispose method will get called as soon as the scope of the using statement is complete. If it is managed code, then no need to dispose of it. Just let the garbage collector do its work.

杀手六號 2024-10-13 15:35:06

使用您自己的 try/finally 块,它执行与“using”类似的逻辑,但仅在设置了 useNetworkAccess 时才进行处理。请注意,如果 useNetworkAccess 可能受到其他线程的影响,您应该复制其值并使用该副本来创建资源和处置它。

Use your own try/finally block, which performs similar logic to the 'using', but only does the dispose if useNetworkAccess is set. Note that if useNetworkAccess could be affected by other threads, you should copy its value and use that copy both for creating the resource and disposing it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文