[英]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.