Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use C# Generic Func<T,Tresult>?

Tags:

c#

generics

func

I have been looking at C#'s Generic function delegates (Func) feature.

Example:

// 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));

I'm struggling to think of a real life scenario where they might be useful in my own applications. So I thought I would put the question out there. \

I'd greatly appreciate your thoughts.

like image 843
K-Dawg Avatar asked Nov 22 '25 11:11

K-Dawg


1 Answers

Say one needs to time method calls for reporting purposes. Placing the timing code inside the function is not feasible for maintenance reasons.

So by using the Func call one can do the time operation and not interfere:

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

Then call it with our function to be timed

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

Result:

 00:00:00.0000926: Jabberwocky

Here is an example use of Funct<T,TResult> using the same time motif to time regex vs string.split

var strData = "The rain in Spain";

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

Here is the setup

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);

}

And the results

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

Updating this answer for 2017. This is not a Func but its non return sibling Action; I have found I do a basic form of logging on my classes where I use Dependency Injection from a consumer such as this:

Action<string> ReportIt  { get; set; }

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

The idea is that status reporting is optional, so later in the code I check to see if it is vialble and if so I give status:

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

The consumer of the class calls it such as

 piperInstance.ReportStatus( Console.WriteLine );

which could also be expressed as

 piperInstance.ReportStatus((str) => { Console.WriteLine(str); } );
like image 92
ΩmegaMan Avatar answered Nov 25 '25 03:11

ΩmegaMan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!