【问题标题】:In few words, what can be said about Func<>简而言之,关于 Func<>
【发布时间】:2010-04-18 09:05:13
【问题描述】:

我已经看到 Func 有一段时间了,我已经设法避免它(现在)。但是,现在看来我永远无法躲避它。例如,我尝试了 Dynamic Linq,但几乎所有内容都是基于 Func 的。我已经尝试过我的一本书(C# 2008/Deitel&Deitel)和 MSDN,但我还没有得到它。他们都直奔主题。

  1. 关于 Func 可以说(几句话)
  2. 我可以在网络上获取一些链接,让我开始处理这件事吗?

感谢您的帮助

【问题讨论】:

  • Jon Skeet 关于 c 锐化的书有几章非常精彩,以及为什么它对 lambda 函数和 linq 如此重要。
  • Func 或泛型委托没有什么可怕的,也没有理由避免使用——它们只是代表带有一定数量参数的通用方法的委托。
  • 您可能想查看关于 SO 的各种 Func 问题:stackoverflow.com/questions/tagged/func

标签: c# func


【解决方案1】:

Func&lt;&gt; 是一个通用委托 - 它使用起来非常方便,因为您不必为每个参数/返回类型组合创建自己的委托。
之前,您必须编写如下内容:

public delegate long MyDelegate( int number );

public void Method( IEnumerable<int> list, MyDelegate myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

您必须发布您的委托,以便用户可以正确调用您的方法。尤其是当您需要一堆不同的委托时,您最终会为每个参数列表和返回类型发布一个。
使用Func&lt;&gt;,您只需写:

public void Method( IEnumerable<int> list, Func<int, long> myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

这与第一个代码示例的含义相同 - Func&lt;int, long&gt; 定义了一个接受一个整数参数并返回一个 long 值的委托。

当然你也可以使用更长的参数列表:Func&lt;int, int, bool, long&gt; 仍然会返回一个 long 值,而它需要两个 ints 和一个 bool em> 值。如果你想要一个没有返回值的委托,你必须使用Action&lt;&gt;,它的返回类型是void

编辑(按要求):如何在我的示例中调用方法

对于调用者来说,MyDelegateFunc&lt;&gt; 的解决方案没有区别。在这两种情况下,他都有三个选项来调用该方法:

使用 lambda 表示法(需要 C# 3.0,可能是短方法的最佳解决方案):

Method( myList, i => i * i );

通过使用匿名方法(需要 C# 2.0):

Method( myList, delegate( int i )
{
    return i * i;
} );

或者使用真实的方法作为参数:

Method( myList, Square );

private static long Square( int number )
{
    return number * number;
}

【讨论】:

【解决方案2】:

Func&lt;...&gt; 是委托类型的家族,它们返回一些值,并接受一些参数;例如:

  • Func&lt;int,bool&gt; 只是接受一个 int 并返回一个 bool 的东西(返回总是在最后);例如谓词:

    int[] data = {1,2,3,4,5};
    var odd = data.Where(i => i % 2 == 0);
    
  • Func&lt;string&gt;是返回字符串的方法,如() =&gt; "hello world";

  • Func&lt;DateDtime, TimeSpan, DateTime&gt; 可能类似于 (when,howLong) =&gt; when + howLong;

同样,Action&lt;...&gt; 的作用相同,但没有返回类型。

Func&lt;...&gt; 没有什么神奇之处——它只是表达委托的一种更简单的方式,而 a:使用泛型(对 LINQ 有用),或者 b:不需要您查找参数是什么;如果委托类型不明确(例如PipeStreamImpersonationWorker),则可能很难知道它需要什么;如果将其表示为可比较的Action,则很明显它不接受任何参数并返回void

【讨论】:

    【解决方案3】:

    这可能会有所帮助。假设每次看到Func&lt;int, string&gt;,你都会想:

    interface IFuncIntString
    {
        string Invoke(int x);
    }
    

    也就是说,委托是一个实现了这个接口的对象。它有一个称为 Invoke 的方法,该方法接受一个 int 并返回一个字符串。

    现在添加一个功能,您可以在通话中省略“Invoke”,这样您就拥有了一个代表。

    【讨论】:

    • 我喜欢这样看待代表。
    • 向 Java 程序员解释它的最佳方式 ;)
    【解决方案4】:

    Func&lt;int&gt;(例如)是一个类型(就像string 是一个类型一样)。所以你用它来声明变量、字段、参数等等。

    它代表一个计算,只要你问它答案就可以完成:

    Func<int> f = () => DateTime.Now.Second;
    
    // elsewhere...
    
    Console.WriteLine( f() );
    

    注意如何像方法一样调用它。 Func 有许多重载版本以支持不同数量的参数。最后一个类型参数是返回类型。

    Func<int, string> quoteInt = n => "\"" + n + "\"";
    
    Console.WriteLine( quoteInt(3) );
    

    Func 是委托类型。您可以声明自己的,但使用Func 更容易。如果您想返回void,请使用Action 而不是Func。如果您需要outref 参数,则只需声明自定义委托。

    将 lambda 分配给 Func 时,您可以引用局部变量。这是非常强大的;这意味着Func 不仅仅是代码;它有数据。所以它就像一个具有单一方法的对象(从技术上讲,它是 - 该方法称为Invoke,当您调用委托时编译器会为您隐式调用该方法)。

    语法() =&gt; 可以放在任何表达式之前,表示“现在不要这样做,推迟到以后”。它允许您初始化捕获延迟计算的委托。然后可以将语法() 放在委托之后以实际触发计算。所以后缀() 是前缀() =&gt; 的反义词。

    【讨论】:

      【解决方案5】:

      你可以从101 Linq Samples开始。

      简而言之,Func&lt;&gt; 是一个委托,其中最后一个类型参数是返回类型。

      所以,Func&lt;int,bool&gt; 是一个接受 int 参数并返回 bool 的委托。

      【讨论】:

        【解决方案6】:

        Func<... t> 是委托。 其中 T 是返回类型,所有其他 - 输入参数。

        【讨论】:

          【解决方案7】:

          如果您曾经在 c# 中使用过 => 运算符,并且您可能已经使用过,那么您已经使用过 Funcs。您只是没有明确声明它们。

          所以,如果你写一个像

          这样的语句
          var peopleWhoLikeBlue = people.Where(person => person.FavoriteColor == "Blue");
          

          您将 Func&lt;Person, bool&gt; 传递给 Where() 方法。

          如果你想罗嗦,你可以像这样重写那个语句:

          Func<Person, bool> favoriteColorIsBlue = person => person.FavoriteColor == "Blue";
          var peopleWhoLikeBlue = people.Where(favoriteColorIsBlue);
          

          你会得到同样的结果。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-03-12
            • 2016-03-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-14
            • 1970-01-01
            • 2010-10-02
            相关资源
            最近更新 更多