帮我用out关键字清理这个疯狂的lambda

Sar*_*els 0 c# lambda refactoring delegates

我的代码看起来很难看,而且我知道必须有更好的方法来做我正在做的事情:

private delegate string doStuff(
    PasswordEncrypter encrypter, RSAPublicKey publicKey,
    string privateKey, out string salt
);

private bool tryEncryptPassword(
    doStuff encryptPassword,
    out string errorMessage
)
{
    ...get some variables...
    string encryptedPassword = encryptPassword(encrypter, publicKey,
        privateKey, out salt);
    ...
}
Run Code Online (Sandbox Code Playgroud)

到目前为止这个东西并没有打扰我.这就是我打电话tryEncryptPassword看起来如此丑陋,并且有重复,因为我用两种方法调用它:

public bool method1(out string errorMessage)
{
    string rawPassword = "foo";
    return tryEncryptPassword(
        (PasswordEncrypter encrypter, RSAPublicKey publicKey,
            string privateKey, out string salt) =>
            encrypter.EncryptPasswordAndDoStuff( // Overload 1
                rawPassword, publicKey, privateKey, out salt
            ),
        out errorMessage
    );
}

public bool method2(SecureString unencryptedPassword,
    out string errorMessage)
{
    return tryEncryptPassword(
       (PasswordEncrypter encrypter, RSAPublicKey publicKey,
           string privateKey, out string salt) =>
           encrypter.EncryptPasswordAndDoStuff( // Overload 2
               unencryptedPassword, publicKey, privateKey, out salt
           ),
       out errorMessage
   );
}
Run Code Online (Sandbox Code Playgroud)

丑陋的两个部分:

  • 由于单个out参数,我必须显式列出lambda表达式中的所有参数类型.
  • EncryptPasswordAndDoStuff除了第一个参数之外,两个重载采用所有相同的参数,可以是a string或a SecureString.所以method1并且method2几乎相同,他们只是调用不同的重载EncryptPasswordAndDoStuff.

有什么建议?

编辑(解决方案):我最终使用了Jeff的建议并改变了重载EncryptPasswordAndDoStuff以返回一个实例EncryptionResult.然后我不需要显式定义delegate,我使用以下代码:

private bool tryEncryptPassword(KeysAndEncrypter keys,
    Func<EncryptionResult> encryptPassword,
    out string errorMessage
) { ... }

private class KeysAndEncrypter
{
    public RSAPublicKey PublicKey { get; set; }
    public string PrivateKey { get; set; }
    public PasswordEncrypter Encrypter { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这里是内容method1,以method2变得非常相似:

string rawPassword = "foo";
KeysAndEncrypter keys = getEncryptionKeys();
return tryEncryptPassword(keys, () =>
    keys.Encrypter.EncryptPasswordAndDoStuff(
        rawPassword, keys.PublicKey, keys.PrivateKey
    ),
    out errorMessage
);
Run Code Online (Sandbox Code Playgroud)

Jef*_*nal 5

您可以引入一个新类型来表示委托的返回值:

 public class EncryptionResult {
     public string EncryptedValue { get; set; }
     public string Salt { get; set; }
 }
Run Code Online (Sandbox Code Playgroud)

...并将委托更改为以下内容:

 private delegate EncryptionResult doStuff(
     PasswordEncrypter encrypter, 
     RSAPublicKey publicKey,
     string privateKey);
Run Code Online (Sandbox Code Playgroud)