2015-07-11 87 views
2

我一直在尋找的C#泛型函數委託(Func鍵)功能。什麼時候應該使用C#泛型函數功能<T,Tresult>?

例子:

// Instantiate delegate to reference UppercaseString method 
Func<string, string> convertMethod = UppercaseString; 
string name = "Dakota"; 

// Use delegate instance to call UppercaseString method 
Console.WriteLine(convertMethod(name)); 

我竭力想一個真實的生活場景,他們可能是在我自己的應用程序非常有用的。所以我想我會在那裏提出這個問題。 \

我會非常感謝您的想法。

+2

查看IEnumerable ''Where'()''和其他extesnion方法的linq源代碼,你會明白它在哪裏有用以及如何使用 –

+0

可能的重複[你如何使用Func < >和Action <>在設計應用程序時?](http://stackoverflow.com/questions/1537404/how-do-you-use-func-and-action-when-designing-applications) –

+3

我結合字典和func( 'Dictionary >'在讀取非託管資源時對特定鍵執行一些操作。 –

回答

7

假設某人需要爲了報告目的而調用方法調用。出於維護原因,將時間代碼放在函數內部是不可行的。

因此,通過使用該Func調用一個可以做時間的操作,不干擾:

static void Time<T>(Func<T> work) 
{ 
    var sw = Stopwatch.StartNew(); 
    var result = work(); 
    Console.WriteLine(sw.Elapsed + ": " + result); 
} 

然後用我們的函數調用它來進行定時

Time(() => { return "Jabberwocky"; }); 

結果:

00:00:00.0000926: Jabberwocky 

他再是使用相同的時間基序時間正則表達式VS string.split

var strData = "The rain in Spain"; 

Time((str) => { return Regex.Split(str, @"\s"); }, strData); 
Time((str) => { return str.Split(); },    strData); 

這裏的示例性使用的Funct<T,TResult>是設置

static void Time<T,S>(Func<T,S> work, T strToSplit) 
{ 
    var sw = Stopwatch.StartNew(); 
    var result = work(strToSplit); 
    sw.Stop(); 

    var joined = string.Join(", ", result as string[]); 
    Console.WriteLine("{0} : {1}", sw.Elapsed, joined); 

} 

而且結果

00:00:00.0000232 : The, rain, in, Spain 
00:00:00.0000021 : The, rain, in, Spain 

更新2017年的答案。這不是Func,而是其不歸屬的兄弟Action ;我發現我做我的班記錄的基本形式,我使用依賴注入從消費者像這樣:

Action<string> ReportIt { get; set; } 

public void ReportStatus(Action<string> statusReporter) 
{ 
    ReportIt = statusReporter; 
} 

的想法是,狀態報告是可選的,所以在我檢查代碼後看它是否是vialble如果是的話,我給狀態:

ReportIt?.Invoke("Running - Connection initiated"); 

類的消費者稱之爲如

piperInstance.ReportStatus(Console.WriteLine); 

whic h後也可表現爲

piperInstance.ReportStatus((str) => { Console.WriteLine(str); }); 
1

有點長的評論(製作社區的wiki)

講解使用情況下,最好的辦法是爲fucntional map功能。在C#中調用Select

假設您有一個字符串列表,map將允許您更改字符串。

如你例子:

somewords.Select(Uppercase)

somewords.Select(x = Uppercase(x))

somewords.Select(x => x.ToUpper())

但不限於串來串轉換。假設你想獲得的所有字符串的長度的列表,你可以簡單地做:

somewords.Select(x => x.Length)

上面會返回一個整數列表(或任何在你的語言使用)。

一旦你開始與其他高階函數結合這一點,事情就變得有趣:)

讓我們再回到前面的例子,但是說你想要的最長的字符串的長度。你有很多選擇去做:

somewords.Select(x => x.Length).Max() 
somewords.OrderByDescending(x => x.Length).First() 
// or even 
somewords.Max(x => x.Length) 

而且可能還有一些我錯過了。最後,這一切都可以幫助你表達自己的意圖,而不必做很多額外的工作(如最後一個例子)。

注:

在上述所有情況下,x => x.Length可能已被取代的人得以與獲取長度的任何功能,說Foo。例如

int Foo(string s) 
{ 
    return s.Length; 
} 

所以somewords.Max(Foo)是一樣的。

1

剛纔看到了一個有趣的現實生活中的例子:

public static List<Transaction> ReadAll(Settings settings, Func<string, FileInfo[]> getFilesOfType) 
{ 
    FileInfo[] files = getFilesOfType("CashRevenue"); 
    // does stuff with files 
} 

這是由

var transactions = FileParser.ReadAll(m_status.FilesByType) 

提供功能FilesByType作爲參數調用

public FileInfo[] FilesByType (string type) 
{ 
    return result = Files.Where(f => f.Type == type) 
       .Select(f => new FileInfo(f.LocalPath)) 
       .ToArray(); 
} 

其中的文件是一個集合屬性,可以使用字符串參數過濾到FilesByType

相關問題