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

C#: Is there a clean pattern for finding the right object combined with using?

我想要一个 clean/compact 模式,它是异常安全的并且可以正确处理 rulesKey,即使有东西被抛出。这对于 using 似乎是不可能的(除非可能是 4 usings 但这看起来很冗长并且打开了我什至不需要打开的额外资源)。让我明白的是,这在 C++ 中会如此 direct/easy。有什么好的解决办法吗?

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

你可以使用

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
}

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. MSDN

您还可以执行以下操作。该示例是硬编码的,但您可以轻松地从文件或数据库或其他任何地方加载路径。这将允许您添加额外的键而不会使 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;
}