Func委托与功能

时间:2010-06-24 19:22:14

标签: c# delegates

有人可以告诉我使用委托的优势而不是如下所示调用函数本身(或者换句话说为什么选择选项A而不是选项B)?我昨晚看了某人的linq代码,他们有类似于Option A的东西,但它被用来返回编译的linq查询。

我意识到前者现在可以传递给其他功能......只是不确定它的实用性。顺便说一句,我意识到这不会按原样编译..在发布之前取消注释其中一个功能。 TYIA

class Program
{
    static void Main(string[] args)
    {   
        Console.WriteLine(SayTwoWords("Hello", "World"));
        Console.ReadKey();
    }

    // Option A
    private static Func<string, string, string>
        SayTwoWords = (a, b) => String.Format("{0} {1}", a, b);

    // Option B
    private static string SayTwoWords(string a, string b)
    {
        return String.Format("{0} {1}", a, b);
    }        
}

************ EDIT ************

不确定它是否更好地解释了我的问题,但这里是一个最初让我思考这个问题的代码类型的例子:

public static class clsCompiledQuery
{
    public static Func<DataContext, string, IQueryable<clsCustomerEntity>>
        getCustomers = CompiledQuery.Compile((DataContext db, string strCustCode)
            => from objCustomer in db.GetTable<clsCustomerEntity>()
            where objCustomer.CustomerCode == strCustCode
            select objCustomer);
}

以这种方式编写函数有什么好处吗?

6 个答案:

答案 0 :(得分:13)

您发布的代码没有任何优势。在您的代码中,使用委托只会增加复杂性以及额外的运行时成本 - 因此您最好直接调用该方法。

然而,代表有很多用途。 “传递”到其他方法是主要用法,虽然存储函数并在以后使用它也非常有用。

LINQ完全基于这个概念。当你这样做时:

var results = myCollection.Where(item => item == "Foo");

您将委托(定义为lambda:item => item == "Foo")传递给LINQ库中的Where函数。这是使它正常工作的原因。

答案 1 :(得分:4)

代表的一个非常有用的功能是你可以在任何你想要的地方发送它们。就像在任何地方都需要你的功能一样。一个很重要的用途是事件处理。假设您有一个按钮,当用户单击此按钮时,您希望调用任意数量的函数。如果你想到这一点,有几种方法可以做到这一点:

你可以: 调用一个调用你想要调用的其他函数的函数。 这意味着对于要调用的每个新函数,必须将其硬编码到此函数中。非常烦人。

OR 您可以拥有要呼叫的每个功能的名称的公共列表(代表),任何人都可以随时添加或删除这些功能,而点击事件的所有者不必知道甚至不做任何有关它们的任何工作。当click事件发生时,列表中的每个事件都会被调用并发送相同的参数,您就完成了。

答案 2 :(得分:3)

只有在必须传递委托时才有用。如果你可以在编译时解决这个问题,那就不太有用了。

答案 3 :(得分:2)

答案 4 :(得分:1)

答案 5 :(得分:1)

// Option A
private static Func<string, string, string>
    SayTwoWords = (a, b) => String.Format("{0} {1}", a, b);

// Option B
private static string SayTwoWords(string a, string b)
{
    return String.Format("{0} {1}", a, b);
}

在上述情况下,选项B是我要使用的,除非我需要更改SayTwoWords的功能。在选项A的情况下,可以为SayTwoWords分配不同的功能。抓住更详细的差异in this answer

存在选项A有意义的情况。考虑一种必须将表达式编译为委托的情况。由于编译表达式很重,所以你只想做一次。这样的模式有助于:

public static class Cache<T> 
{ 
    public static readonly Func<T> Get = GetImpl();

    static Func<T> GetImpl()
    {
        //build expression and return compiled delegate
    }
}

而不是

public static class Cache<T> 
{
    public static T Get()
    {
        //build expression, compile delegate and invoke the delegate
    }
}

在第一种情况下,当您致电Get时,GetImpl仅执行一次,而在第二种情况下,每次都会调用(昂贵的)Get