2010-04-18 15 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); 

,你會得到相同的結果。

相關問題