【问题标题】:Convert Func<T, String> to Func<T, bool>将 Func<T, String> 转换为 Func<T, bool>
【发布时间】:2011-10-31 13:52:16
【问题描述】:

我想我的大脑正在爆炸,试图弄清楚 Funcs...如果这没有意义,我很抱歉,现在对我来说很有意义,但它已经是漫长的一天了....

1) 假设给定一个函数,它接受 T 并输出一个字符串:

 Func<T, string> 

你能把它转换成一个接受 T 并基于某种逻辑返回布尔值的 func(在这种情况下,如果返回的字符串为空 (String.IsNullOrWhiteSpace)?

 Func<T, bool> 

2) 如果给你一个

,你能做同样的事情吗?
Expression<Func<T, string>>

并需要将其转换为

Func<T, bool>

根据返回的字符串是否为空(String.IsNullOrWhiteSpace)返回真/假?

谢谢

【问题讨论】:

    标签: c# func


    【解决方案1】:

    你能不能把它定义为一个单独的委托:

    Func<T, string> func1 = t => t.ToString();
    Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));
    

    【讨论】:

      【解决方案2】:

      对于第一部分,您甚至可以创建一些“高阶”函数:

      
      
      Func<A,C&gt MapFun<A,B,C&gt(Func<A,B&gt input, Func<B,C&gt transf)
      {
         return a => transf(input(a));
      }
      
      

      搭配使用

      
      
      Func <T,string> test = ...
      var result = MapFun(test, String.IsNullOrWhiteSpace);
      
      

      (我希望 C# 类型类型推断在这里起作用)

      如果您将其定义为 Func 上的扩展,它会变得更加容易:

      
      public static class FuncExtension
      {
          public static Func<A,C> ComposeWith<A,B,C&gt(this Func<A,B> input, Func<B,C> f)
          {
               return a => f(input(a));
          }
      }
      

      这是一个非常简单的测试:

      
      Func<int, string&gt test = i =&gt i.ToString();
      var result = test.ComposeWith(string.IsNullOrEmpty);
      

      对于第二个:我认为您可以将表达式编译成“真正的”Func,然后使用上面的代码。 see MSDN Docs on Expression.Compile

      PS:重命名函数以更好地匹配它的意图(它的函数组合)

      【讨论】:

      • 我猜你的意思是“类型推断”而不是“类型干扰”;)
      • 谢谢!在您查看答案之后,它完全有道理。多个正确答案,但您的答案是第一个且完整的,因此您可以进行检查。谢谢大家!
      【解决方案3】:

      对于第一部分,该技术称为函数组合,即您组合 2 个函数来创建一个新函数。 在您的情况下,您有一个函数Func&lt;T,String&gt; 和另一个类型为Func&lt;string,bool&gt; 的函数(如字符串空或null),使用函数组合您可以组合这两个函数来创建一个Func&lt;T,Bool&gt; 类型的新函数

      大多数函数式编程语言都已经在其标准库或语言本身中定义了这种函数组合。但是,如果语言支持函数作为一等值,那么为您的语言创建一个并不难。

      在 C# 中,您可以使用以下函数来编写函数:

      public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b)
      {
          return (v) => b(a(v));
      }
      

      【讨论】:

        【解决方案4】:

        To 1:是(你也可以参数化 bool 和 string):

        Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
        {
            return x => map(source(x));
        }
        

        To 2:可以,但需要先编译表达式:

        Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
        {
            return x => compose(source.Compile(), map)
        }
        

        .Compile 会将表达式编译为动态 CLR 方法,您可以使用返回的委托调用该方法。

        您可以像这样使用此代码:

        Func<int, string> ts = i => i.ToString();
        var result = Compose(ts, string.IsNullOrEmpty);
        

        顺便说一句,在这种情况下,你真的应该写一个高阶函数。你在这里做的(代数)是组成幺半群。还记得function composition 吗? f . g := f(g(x)) 就是你在这里所做的。

        将源视为g:A-&gt;B 并将映射视为f:B-&gt;C(其中A、B 和C 是集合),因此f . g 的结果是h:A-&gt;C。顺便说一句,. 运算符通常内置于函数式编程语言中,例如 Haskell,并实现与 compose 函数相同的功能(但语法更简洁)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-05
          相关资源
          最近更新 更多