C# conditional using block statement

后端 未结 10 1695
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-02 07:25

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 acc

相关标签:
10条回答
  • 2021-02-02 07:45

    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!

    0 讨论(0)
  • 2021-02-02 07:46

    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();
           }
        }
    }
    
    0 讨论(0)
  • 2021-02-02 07:46

    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.

    0 讨论(0)
  • 2021-02-02 07:52

    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.

    0 讨论(0)
  • 2021-02-02 07:54

    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);
    }
    
    0 讨论(0)
  • 2021-02-02 07:55

    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.

    0 讨论(0)
提交回复
热议问题