2010-04-18 31 views
20

我一直在玩功能<>有一段时间了,我已经设法避免它(现在)。但是,现在看来我无法永远躲避它。例如,我尝试了动态Linq,但几乎所有的东西都是按照Func <>。我试过我的一本书(C#2008/Deitel & Deitel)和MSDN,但我还没有得到它。他们全都直奔主题。简而言之,关于Func有什么可说的呢?

  1. 什么,可Func键<说(在几句话)>
  2. 我可以得到网页,可以让我开始对这个问题的一些链接?

感谢您的帮助

+1

Jon Skeet的关于c sharp的书籍在这方面有很好的几章,为什么它对lambda函数和linq非常重要。 – 2010-04-18 10:57:29

+0

没有什么可怕的,也没有理由避免,Func或泛型委托 - 它们只是表示采用一定数量参数的常规方法的委托。 – thecoop 2010-04-18 15:40:44

+0

你可能想看看SO上的各种Func问题:http://stackoverflow.com/questions/tagged/func – 2010-04-18 15:51:37

回答

33

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>限定代表,它有一个整数参数,并返回一个长值。

当然你也可以使用更长的参数列表,太:Func<int, int, bool, long>仍然会返回一个价值,同时它有两个整数布尔值。如果您想要一个没有返回值的代表,您将不得不使用Action<>,它将有void作为返回类型。

EDIT(由请求):如何调用该方法在我的例子

对于呼叫者,存在与MyDelegateFunc<>溶液之间没有差别。在这两种情况下,他有三个选择要调用的方法:

使用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; 
} 
+0

非常好的探索! – John 2010-04-18 15:36:35

+0

很好的解释。包括使用/调用Method的例子也不错。 – 2010-04-18 15:47:01

+0

@Metro:我加了一些例子,如何调用方法 – tanascius 2010-04-18 17:02:08

3

你可以101 Linq Samples开始。

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

因此,Func<int,bool>是一个代表,它需要参数int并返回bool

12

Func<...>家族委托类型,返回一些值,并采取一些参数;例如:

  • Func<int,bool>仅仅是一些把一个int和返回一个布尔(返回总是在端部);例如谓词:

    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

1

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

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。如果您需要outref参数,则只需声明自定义代表。

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

语法() =>可以放在任何表达式之前,以表示“现在不要执行此操作,将其延迟至以后”。它允许你初始化一个捕获延迟计算的委托。然后可以在代理之后放置语法()以实际触发计算。所以后缀()是前缀() =>的一种。

+0

+1表示一个简洁的解释。 – 2010-04-18 09:49:57

10

这可能会有帮助。假设每次你看到Func<int, string>时候你想对自己说:

interface IFuncIntString 
{ 
    string Invoke(int x); 
} 

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

现在再补充一点,您可以在通话中省略“调用”功能,并且您已经拥有了一个委托人。

+0

这就是我喜欢想象的代表。 – kenny 2010-04-18 15:47:48

+2

将它解释给Java程序员的最佳方法;) – juharr 2010-04-18 15:50:11

1

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

所以,如果你写这样

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

你传递一个Func<Person, bool>到哪里()方法的声明。

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

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

,你会得到相同的结果。

相关问题