繁体   English   中英

c#中的函数编程:如何使用语句嵌套并允许代码块修改返回的数据?

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM