20

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

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

感谢您的帮助

4

7 回答 7

32

Func<>是一个通用委托 - 它使用起来非常方便,因为您不必为每个参数/返回类型组合创建自己的委托。
早些时候,您必须编写如下内容:

public delegate long MyDelegate( int number );

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

您必须发布您的委托,以便用户可以正确调用您的方法。特别是当您需要一堆不同的委托时,您最终会为每个参数列表和返回类型发布一个。
Func<>你一起写:

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

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

当然,您也可以使用更长的参数列表:Func<int, int, bool, long>仍然会返回一个long值,而它需要两个int和一个bool值。如果您希望委托没有返回值,则必须使用Action<>void作为返回类型。

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

MyDelegate对于调用者,与or的解决方案没有区别Func<>。在这两种情况下,他都有三个选项来调用该方法:

使用 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;
}
于 2010-04-18T09:17:33.367 回答
12

Func<...>是一系列委托类型,它们返回一些值并接受一些参数;例如:

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

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

  • Func<DateDtime, TimeSpan, DateTime>可能是这样的(when,howLong) => when + howLong;

同样Action<...>,也有相同的功能,但没有返回类型。

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

于 2010-04-18T09:11:09.383 回答
10

这可能会有所帮助。假设你每次看到Func<int, string>你都会想:

interface IFuncIntString
{
    string Invoke(int x);
}

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

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

于 2010-04-18T15:29:56.630 回答
7

Func<int>(例如)是一种类型(以一种类型的方式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. out如果您需要或ref参数,您只需要声明自定义委托。

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

该语法() =>可以放在任何表达式之前,表示“现在不要这样做,推迟到以后”。它允许您初始化捕获延迟计算的委托。然后可以将语法()放在委托之后以实际触发计算。所以 suffix()是 prefix 的对立面() =>

于 2010-04-18T09:14:18.583 回答
3

您可以从101 Linq Samples开始。

简而言之,Func<>是一个委托,其中最后一个类型参数是返回类型。

所以,Func<int,bool>是一个接受一个int参数并返回一个bool.

于 2010-04-18T09:08:21.003 回答
1

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

于 2010-04-18T09:12:02.407 回答
1

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

所以,如果你写一个像

var peopleWhoLikeBlue = people.Where(person => person.FavoriteColor == "Blue");

您将 a 传递给Func<Person, bool>Where() 方法。

如果您想罗嗦,可以像这样重写该语句:

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

你会得到同样的结果。

于 2010-04-18T16:38:59.333 回答