C#:找到合适的对象与使用相结合是否有一个干净的模式?

时间:2016-04-21 21:17:42

标签: c# registry using null-coalescing-operator

我想要一个异常安全的干净/紧凑模式,并且即使抛出某些东西也会正确处理rulesKeyusing似乎无法做到这一点(除非可能是4 using,但这看起来很冗长并打开了我甚至可能不需要打开的额外资源。让我感到惊讶的是,这在C ++中会如此直接/轻松。有一个很好的解决方案吗?

{
    RegistryKey rulesKey = null;
    rulesKey = rulesKey ?? Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Company\\Internal\\Product");
    rulesKey = rulesKey ?? Registry.LocalMachine.OpenSubKey("Software\\Company\\Company\\Internal\\Product");
    rulesKey = rulesKey ?? Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Company\\Product");
    rulesKey = rulesKey ?? Registry.LocalMachine.OpenSubKey("Software\\Company\\Product");

    // Code using rulesKey, might throw

    rulesKey.Close();
}

2 个答案:

答案 0 :(得分:8)

您可以使用

using (RegistryKey rulesKey = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Company\\Internal\\Product")
                                ?? Registry.LocalMachine.OpenSubKey("Software\\Company\\Company\\Internal\\Product")
                                ?? Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Company\\Product")
                                ?? Registry.LocalMachine.OpenSubKey("Software\\Company\\Product"))
{
    //use rulesKey here
}

由于

  

using语句确保即使在对象上调用方法时发生异常,也会调用Dispose。您可以通过将对象放在try块中然后在finally块中调用Dispose来实现相同的结果;实际上,这就是编译器如何翻译using语句。 MSDN

答案 1 :(得分:0)

您还可以执行以下操作。该示例是硬编码的,但您可以轻松地从文件或数据库或其他任何方式加载路径。这将允许您添加其他键而不会膨胀using语句。它也会加强限制访问

List<string> keyPaths = GetKeyPaths();
private void DoStuff()
{        
    // key is disposed when leaving using block
    using(var key = OpenFirstAvailableKey())
    {
        if(key == null)
        {
            // handle error
        }

        // do stuff
    }
}

private RegistryKey OpenFirstAvailableKey()
{
    RegistryKey result = null;
    try
    {
        foreach(var key in keyPaths)
        {
            result = Registry.LocalMachine.OpenSubKey(key);
            if(result != null)
            {
                break;
            }
        }    
    }
    catch (System.Exception)
    {
        // handle or throw        
        throw;
    }

    return result;
}

private List<string> GetKeyPaths()
{
    List<string> paths = new List<string>();
    // Load from db or file or whatever...or just hardcode
    paths.Add("Software\\Wow6432Node\\Company\\Internal\\Product");
    paths.Add("Software\\Company\\Company\\Internal\\Product");
    paths.Add("Software\\Wow6432Node\\Company\\Product");
    paths.Add("Software\\Company\\Product");

    return paths;
}