[英]Functional programming in c#: how do I nest using statements and allow code blocks to modify returned data?
我正在围绕c#中的函数式编程,因此我可以减少代码中的副作用量,并使测试更容易并推广我的代码,因此重构更容易。 但是,我在确定如何使用通用的使用块来using
语句进行嵌套时遇到了问题。 考虑以下:
public static class Disposable
{
public static TResult Using<TDisposable, TResult>
(
Func<TDisposable> factory,
Func<TDisposable, TResult> fn) where TDisposable : IDisposable
{
using (var disposable = factory())
{
return fn(disposable);
}
}
}
我使用以下代码示例调用此代码:
Disposable.Using(
StreamFactory.GetStream,
stream => new byte[stream.Length].Tee(b => stream.Read(b, 0, (int)stream.Length)))
我将这个修改后的using
语句的输出传递给管道中的另一个方法。
然而,我确实遇到了一个警告,我被卡住了。
如果我想使用嵌套的using语句,但是对我想要传递的返回项进行修改,该怎么办?
通过重用上面描述的Disposable
类来考虑以下内容:
Disposable.Using(
() => new PasswordDeriveBytes(PasswordConstants.CryptoKey, null),
password => Disposable.Using(
() => new RijndaelManaged(),
symmetricKey =>
Disposable.Using(
() => symmetricKey.CreateEncryptor(password.GetBytes(PasswordConstants.KeySize/8), Encoding.ASCII.GetBytes(PasswordConstants.Cipher)),
encryptor => encryptor)
));
这段代码有效...但是,如果我想改变symmetricKey's
加密模式怎么办?
以下不起作用:
Disposable.Using(
() => new PasswordDeriveBytes(PasswordConstants.CryptoKey, null),
password => Disposable.Using(
() => new RijndaelManaged(),
symmetricKey =>
{
symmetricKey.Mode = CipherMode.CBC; // ← this causes an issue, and also the fact that I made a **code block** here
Disposable.Using(
() => symmetricKey.CreateEncryptor(password.GetBytes(PasswordConstants.KeySize/8), Encoding.ASCII.GetBytes(PasswordConstants.Cipher)),
encryptor => encryptor);
}
));
我可以做些什么来允许修改通过我在上面创建的通用Disposable.Using
方法传递的变量?
如果我想使用嵌套的using语句,但是对我想要传递的返回项进行修改,该怎么办?
让我们从简化您的Disposable.Using
开始,我们不需要通用的TDisposable
- 删除它并只使用IDisposable
。
public static class Disposable
{
public static TResult Using<TResult>(
Func<IDisposable> factory,
Func<IDisposable, TResult> use)
{
using (var disposable = factory())
{
return use(disposable);
}
}
}
另外,正如@juharr所说的那样 - 你错过了一个return
:
Disposable.Using(
() => new PasswordDeriveBytes(PasswordConstants.CryptoKey, null),
password => Disposable.Using(
() => new RijndaelManaged(),
symmetricKey =>
{
symmetricKey.Mode = CipherMode.CBC;
return Disposable.Using(
() => symmetricKey.CreateEncryptor(password.GetBytes(PasswordConstants.KeySize/8), Encoding.ASCII.GetBytes(PasswordConstants.Cipher)),
encryptor => encryptor);
}));
这是由于lambda
函数和anonymous
方法之间的细微差别 。
我想你只是错过了return
。 试试这个。
Disposable.Using(
() => new PasswordDeriveBytes(PasswordConstants.CryptoKey, null),
password => Disposable.Using(
() => new RijndaelManaged(),
symmetricKey =>
{
symmetricKey.Mode = CipherMode.CBC;
return Disposable.Using(
() => symmetricKey.CreateEncryptor(password.GetBytes(PasswordConstants.KeySize/8), Encoding.ASCII.GetBytes(PasswordConstants.Cipher)),
encryptor => encryptor);
}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.