C# Func<;T、 TResult>;委托真实世界使用

C# Func<;T、 TResult>;委托真实世界使用,c#,lambda,anonymous-function,func,C#,Lambda,Anonymous Function,Func,我最近一直在玩委托Func,并创建返回包含lambda的不同实例Func的方法,但我一直在努力想的是,在现实世界中,为什么有人可能想要返回(甚至创建这样的实例) 有一个例子说明他们在哪里做了以下事情 Func<string, string> convertMethod = UppercaseString; private static string UppercaseString(string inputString) { return inputString.ToUpper

我最近一直在玩委托
Func
,并创建返回包含lambda的不同实例
Func
的方法,但我一直在努力想的是,在现实世界中,为什么有人可能想要返回(甚至创建这样的实例)

有一个例子说明他们在哪里做了以下事情

Func<string, string> convertMethod = UppercaseString;
private static string UppercaseString(string inputString)
{
    return inputString.ToUpper();
}
Func convertMethod=大写字符串;
私有静态字符串UppercaseString(字符串输入字符串)
{
返回inputString.ToUpper();
}
虽然它看起来很漂亮,是一个有趣的概念,但我看不出这样的代码有什么优势


因此,这里的人能否提供一些他们必须使用
Func
的真实例子,以及通常为什么要使用此委托?

在LINQ中,您会经常使用它。例如,要将列表中的所有数字加倍:

myList.Select(x => x * 2);
这是一个
Func
。在创建简明代码时,它非常有用。一个真实的例子是在我做的许多塔防游戏中,我用一条线计算了离塔楼最近的敌人:

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

如果你真正想问的是为什么我们一般都有代表:

  • 如果您曾经使用过某个事件,那么您使用了一个委托
  • 如果您曾经使用过LINQ,那么您就使用了委托(从技术上讲,对于
    IQueryable
    提供程序,您使用了表达式,但是对于LINQ to对象,您使用了委托)
委托提供了一种将自己的行为注入另一个对象的方法。最常见的用法是事件。对象公开一个事件,您提供一个函数(匿名或非匿名),该函数在该事件触发时被调用

如果您问我们为什么有
Func
(和类似的)委托,那么主要有两个原因:

  • 当人们在代码中需要特定的委托时,他们必须声明自己的简单委托类型。虽然
    操作
    函数
    委托不能涵盖所有情况,但它们提供起来很简单,可以涵盖许多需要自定义委托的情况
  • 更重要的是,
    Func
    委托在LINQ to对象中广泛用于定义谓词。更具体地说,
    Func
    。这允许您定义一个谓词,该谓词接受
    IEnumerable
    的强类型成员,并使用lambda或普通函数返回布尔值,然后将该谓词传递给LINQ to对象

  • 我认为一个很好的例子是惰性初始化

    var value = new Lazy<int>(() => ExpensiveOperation()); // Takes Func<T>
    
    var value=new Lazy(()=>ExpensiveOperation());//接受Func
    
    首先,
    Func
    不是类,而是委托


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

    需要函数指针的典型示例是让比较函数传递给排序例程。为了拥有不同的排序键,需要为比较函数创建lambda,并将其传递给排序函数

    或者举一个简单的现实例子:

    IEnumerable<Person> FindByLastName(string lastName)
    {
        return Customers.Where(cust => cust.LastName == lastName);
    }
    
    IEnumerable FindByLastName(字符串lastName)
    {
    返回Customers.Where(cust=>cust.LastName==LastName);
    }
    
    在本例中,
    cust=>cust.LastName==LastName
    不仅仅是一个lambda,它还通过捕获
    LastName
    参数来创建一个闭包。换句话说,它创建了一个函数,每次调用
    FindByLastName
    时,该函数都会有所不同。

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

    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表达式增加了相当多的表达能力。它可以编写新的构造,例如并行循环(使用.NET 4.0):


    Funct的一个重要用途是,除了它被嵌入许多框架(如LINQ、模拟工具和依赖项注入容器)之外,还可以使用它来创建一个函数。

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

    我的方法本身只是将文件从XLS转换为XML。但是有必要允许调用代码在需要时指定任意数量的转换,这些转换应在作为xml标记写入之前应用于每个xls单元。例如:将“,”十进制分隔符转换为“.”,抑制千位分隔符,等等(这些转换都是字符串替换)


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

    对你的问题有帮助吗?@Gabe:听起来他是在问为什么我们需要代理,而不是为什么我们特别需要
    Func
    。不,我绝对不是在问为什么我们需要代理。我只是不明白为什么我们需要这个@盖布-现在读这个问题。谢谢…在您的示例中,它是
    Func
    ,而不是
    Func
    。你指的是哪一个?请记住,
    Func
    中的最后一个
    T
    始终是返回值。我参考了Func-更新了我的问题,使之更具体。:-)这有点不同——它显示了为什么
    Func
    有用,但没有显示为什么/where
    Func
    有用。@pst:这是一个不一致的问题-在代码示例中,他指定了一个
    Func
    ,所以我认为这就是他的意思。这是linq和lambda非常棒的用法。代码正式被盗!:-为什么OrderBy(x=>x)-Sorr
    Parallel.ForEach(collection, element => {
        // Process 'element'
    });