帮我用 out 关键字清理这个疯狂的 lambda
我的代码看起来很难看,而且我知道必须有更好的方法来完成我正在做的事情:
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);
...
}
到目前为止,这些东西并没有困扰我。这就是我调用 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
);
}
丑陋的两部分:
- 我必须显式列出 lambda 表达式中的所有参数类型,因为单个
out
参数。 EncryptPasswordAndDoStuff
的两个重载采用除第一个参数之外的所有相同参数,该参数可以是string
或SecureString
。因此,method1
和method2
几乎相同,它们只是调用EncryptPasswordAndDoStuff
的不同重载。
有什么建议吗?
编辑(解决方案):我最终使用了 Jeff 的建议并更改了 EncryptPasswordAndDoStuff
的重载以返回 EncryptionResult
的实例。然后我不需要显式定义的委托
,我使用了以下代码:
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; }
}
这是method1
的内容,method2
是非常相似:
string rawPassword = "foo";
KeysAndEncrypter keys = getEncryptionKeys();
return tryEncryptPassword(keys, () =>
keys.Encrypter.EncryptPasswordAndDoStuff(
rawPassword, keys.PublicKey, keys.PrivateKey
),
out errorMessage
);
My code looks ugly, and I know there's got to be a better way of doing what I'm doing:
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);
...
}
This stuff so far doesn't bother me. It's how I'm calling tryEncryptPassword
that looks so ugly, and has duplication because I call it from two methods:
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
);
}
Two parts to the ugliness:
- I have to explicitly list all the parameter types in the lambda expression because of the single
out
parameter. - The two overloads of
EncryptPasswordAndDoStuff
take all the same parameters except for the first parameter, which can either be astring
or aSecureString
. Somethod1
andmethod2
are pretty much identical, they just call different overloads ofEncryptPasswordAndDoStuff
.
Any suggestions?
Edit (solution): I ended up using Jeff's suggestion and altering the overloads of EncryptPasswordAndDoStuff
to return an instance of EncryptionResult
. Then I didn't need an explicitly defined delegate
, and I used the following code:
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; }
}
And here was the contents of method1
, with method2
being very similar:
string rawPassword = "foo";
KeysAndEncrypter keys = getEncryptionKeys();
return tryEncryptPassword(keys, () =>
keys.Encrypter.EncryptPasswordAndDoStuff(
rawPassword, keys.PublicKey, keys.PrivateKey
),
out errorMessage
);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以引入一种新类型来表示委托的返回值:
...并将委托更改为如下所示:
You could introduce a new type to represent the delegate's return value:
... and change the delegate to something like this:
为什么要为疯狂的 lambda 烦恼呢?
Why bother with the crazy lambda at all?
杰夫的建议是合理的。如果您不想每次需要输出参数时都定义一个新类型,您也可以使用
Tuple
。另一个建议是传入另一个委托来检索错误,而不是使用输出参数。
在调用 method1 之前,您可以将 setError 分配给局部变量。
Jeff's suggestion is reasonable. You could just use a
Tuple<string, string>
too though if you don't want to define a new type each time you need an out parameter.Another suggestion would be to pass in another delegate to retrieve the error rather then using an out param.
Before calling method1, you can assign your setError to a local variable.
另外,如果您不想创建自定义类型,您可以在此处返回一个元组。
在 doStuff 中,只需创建并返回一个元组:
Also, if you don't want to create a custom type, you could return a tuple here.
within doStuff, just create and return a tuple: