开发者

Func<T, TResult> delegate real world uses

I've recently been playing around with the delegate Func<T, TResult> and creating methods that return different instances Func<T, TResult> containing lambda but what I have struggled to come up with is any good real world ideas of why one might want to return (or even create such an instance).

There is an example on MSDN where they do the following...

Func<string, string> convertMethod = UppercaseString;
private static string UppercaseString(string inputString)
{
    return inputString.ToUpper();
}

And although it looks p开发者_如何转开发retty and is an interesting concept I fail to see what advantages such code provides.

So could someone here please provide any real world examples where they have had to use Func<T, TResult> and in general why one might want to use this delegate?


If what you're asking, really, is why we have delegates in general:

  • If you've ever consumed an event, you've used a delegate
  • If you've ever used LINQ, you've used a delegate (technically, with an IQueryable provider you've used an expression, but for LINQ-to-Objects you've used a delegate)

Delegates provide a way of injecting your own behavior into another object. The most common usage is with events. An object exposes an event and you provide a function (anonymous or not) that gets called when that event fires.

If you're asking why we have the Func<T, TResult> (and similar) delegate, then there are two main reasons:

  1. People were having to declare their own simple delegate types when they needed a particular delegate in their code. While the Action<> and Func<> delegates can't cover all cases, they are simple to provide and cover many of the cases where custom delegates were needed.
  2. More importantly, the Func<T, TResult> delegate is used extensively in LINQ-to-Objects to define predicates. More specifically, Func<T, bool>. This allows you to define a predicate that takes a strongly-typed member of an IEnumerable<T> and returns a boolean by using either a lambda or ordinary function, then pass that predicate to LINQ-to-Objects.


You would use it a lot in LINQ. So, for example, to double all the numbers in a list:

myList.Select(x => x * 2);

That's a Func<TIn, TOut>. It's quite useful when creating concise code. A real-world example is in one of the many tower-defence games I made, I calculated the closest enemy to the tower using one line:

enemies.Select(x => tower.Location.DistanceTo(x.Location)).OrderBy(x => x).FirstOrDefault();


I think a great example is lazy initialization.

var value = new Lazy<int>(() => ExpensiveOperation()); // Takes Func<T>


The canonical example of a need for a function pointer is for a comparison function to pass to a sort routine. In order to have different sort keys, you create a lambda for the comparison function, and pass that to the sort function.

Or for a simple real-world example:

IEnumerable<Person> FindByLastName(string lastName)
{
    return Customers.Where(cust => cust.LastName == lastName);
}

In this example, cust => cust.LastName == lastName is not just a lambda, but it creates a closure by capturing the lastName parameter. In othe words, it creates a function, which will be different every time FindByLastName is called.


The Func<T> delegate (and other overloads) give you new ways for writing abstractions in C#. To demonstrate some of the options, here are a couple of C# langauge constructs that could be written using delegates instead:

Thread.Lock(obj, () => { 
    // Safely access 'obj' here
});

Enumerable.ForEach(collection, element => {
    // Process 'element'
});

Exceptions.Try(() => { 
    // Try block
}).With((IOException e) => {
    // Handle IO exceptions
});

These are quite primitive, so it is good to have a language construct for them. However, it demonstrates that Func and lambda expressions add quite a lot of expressive power. It makes it possible to write new constructs such as parallel loop (using .NET 4.0):

Parallel.ForEach(collection, element => {
    // Process 'element'
});


First of all, Func<T> is not a class, it's a delegate.

Basically, you can use it whenever you need a method argument or a property of delegate type if you don't want to declare your own delegate for that.


One great use of Funct<T>, besides the fact that it is embedded in many frameworks such as LINQ, Mocking Tools, and Dependency Injection containers is to use it to create a delegate based factory.


Recently, I wanted the external program calling my method to be able to modify the way it behaves.

My method in itself simply converts a file from XLS to XML. But it was necessary to allow the calling code to specify if needed an arbitrary number of transformations which should apply to each xls cell before being writing as a xml tag. For example : convert the "," decimal separator to ".", suppress the thousand separator, and so on (the transformations were all string replacements).

Then the caller code just had to add an arbitrary number of entries in a dictionary where the key is the pattern and the value is the replacement string for this pattern. My method loops over the dictionary and creates a new Func<string,string> for each entry. Then for each cell the Func<string,string> are applied in sequence.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜