C# conditional using block statement

2020-05-20 07:19发布

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

10条回答
别忘想泡老子
2楼-- · 2020-05-20 07:48

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);
}
查看更多
家丑人穷心不美
3楼-- · 2020-05-20 07:49

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

查看更多
何必那么认真
4楼-- · 2020-05-20 07:52
protected void ValidateExportDirectoryExists()
{
      var access = useNetworkAccess
          ? new Core.NetworkAccess(username, password, domain)
            : null;

      using (access)
      {
          CheckExportDirectoryExists();
      }
}
查看更多
姐就是有狂的资本
5楼-- · 2020-05-20 07:53

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!

查看更多
甜甜的少女心
6楼-- · 2020-05-20 07:54

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.

查看更多
Deceive 欺骗
7楼-- · 2020-05-20 07:55

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();
       }
    }
}
查看更多
登录 后发表回答