Func <t,tresult =“”>委托现实世界使用</t,>

时间:2011-06-01 03:03:50

标签: c# lambda anonymous-function func

我最近一直在玩代理Func<T, TResult>并创建返回包含lambda的不同实例Func<T, TResult>的方法,但我一直在努力想出的是任何一个好的现实世界的想法为什么一个可能想要返回(甚至创建这样的实例)。

MSDN上有一个示例,他们会执行以下操作...

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

虽然它看起来很漂亮并且是一个有趣的概念,但我没有看到这些代码提供的优势。

那么有人可以提供他们必须使用Func<T, TResult>的任何真实世界的例子,并且一般为什么人们可能想要使用这个代表?

8 个答案:

答案 0 :(得分:11)

如果你问的是什么,那就是为什么我们一般会有代表:

  • 如果您曾经使用过某个活动,那么您已经使用了一个代表
  • 如果您曾经使用过LINQ,那么您使用了委托(从技术上讲,使用了IQueryable提供程序,您已经使用了表达式,但是对于LINQ到对象,您使用了委托)< / LI>

代理提供了一种将自己的行为注入另一个对象的方法。最常见的用法是事件。对象公开事件并提供在该事件触发时调用的函数(匿名或非匿名)。

如果你问为什么我们有Func<T, TResult>(和类似的)代表,那么主要有两个原因:

  1. 人们在代码中需要特定委托时必须声明自己的简单委托类型。虽然Action<>Func<>代表无法涵盖所有​​案例,但它们很容易提供并涵盖许多需要自定义代理的案例。
  2. 更重要的是,Func<T, TResult>委托在LINQ-to-Objects中广泛使用来定义谓词。更具体地说,Func<T, bool>。这允许您定义一个带有IEnumerable<T>的强类型成员的谓词,并使用lambda或普通函数返回一个布尔值,然后将该谓词传递给LINQ-to-Objects。

答案 1 :(得分:4)

你会在LINQ中使用它。因此,例如,要将列表中的所有数字加倍:

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

那是Func<TIn, TOut>。在创建简洁代码时非常有用。一个现实世界的例子是我制作的众多塔防游戏之一,我用一条线计算了最接近塔的敌人:

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

答案 2 :(得分:3)

我认为一个很好的例子是延迟初始化。

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

答案 3 :(得分:3)

需要函数指针的规范示例是将比较函数传递给排序例程。为了拥有不同的排序键,您可以为比较函数创建一个lambda,并将其传递给sort函数。

或者是一个简单的现实世界的例子:

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

在此示例中,cust => cust.LastName == lastName不仅仅是lambda,而是通过捕获lastName参数来创建闭包。换句话说,创建一个函数,每次调用FindByLastName时都会有所不同。

答案 4 :(得分:2)

Func<T>委托(以及其他重载)为您提供了在C#中编写抽象的新方法。为了演示一些选项,这里有几个可以使用委托编写的C#语言构造:

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

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

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

这些非常原始,因此为它们提供语言构造是很好的。但是,它表明Func和lambda表达式增加了很多表达能力。它可以编写新的构造,例如 parallel loop (使用.NET 4.0):

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

答案 5 :(得分:1)

首先,Func<T>不是一个类,它是一个委托。

基本上,如果您不想为此声明自己的委托,则可以在需要方法参数或委托类型属性时使用它。

答案 6 :(得分:1)

Funct<T>的一个很好的用途,除了它嵌入许多框架(如LINQ,Mocking Tools和依赖注入容器)这一事实之外,还可以使用它来创建delegate based factory

答案 7 :(得分:0)

最近,我希望外部程序调用我的方法能够修改它的行为方式。

我的方法本身只是将文件从XLS转换为XML。但有必要允许调用代码在写入xml标记之前指定是否需要应用于每个xls单元的任意数量的转换。例如:将“,”小数分隔符转换为“。”,禁止千位分隔符,依此类推(转换都是字符串替换)。

然后调用者代码只需在字典中添加任意数量的条目,其中键是模式,值是此模式的替换字符串。我的方法遍历字典并为每个条目创建一个新的Func<string,string>。然后,对于每个单元格,Func<string,string>按顺序应用。