Func<string,string> 和委托有啥区别?

Posted

技术标签:

【中文标题】Func<string,string> 和委托有啥区别?【英文标题】:What is the difference between Func<string,string> and delegate?Func<string,string> 和委托有什么区别? 【发布时间】:2011-10-12 17:12:33 【问题描述】:

我看到代表有两种形式:

A. Func<string, string> convertMethod = lambda 

B. public delegate string convertMethod(string value);

我不确定这两者之间的实际区别是什么。他们都是代表吗?我相信第一个会使用 lambda,而第二个必须有一种方法来实际执行工作。我可能也很困惑。

【问题讨论】:

Declare delegate manually, use Func<T> or Action<T>? 的可能重复项 【参考方案1】:

首先,您的两个示例正在做两件完全不同的事情。第一个是声明一个通用委托变量并为其分配一个值,第二个只是定义一个delegate 类型。更完整的例子是:

public static class Program

    // you can define your own delegate for a nice meaningful name, but the
    // generic delegates (Func, Action, Predicate) are all defined already
    public delegate string ConvertedMethod(string value);

    public static void Main()
    
        // both work fine for taking methods, lambdas, etc.
        Func<string, string> convertedMethod = s => s + ", Hello!";
        ConvertedMethod convertedMethod2 = s => s + ", Hello!";
    

但更重要的是,Func&lt;string,string&gt;delegate string convertMethod(string) 都能够保存相同的方法定义,无论它们是方法、匿名方法还是 lambda 表达式。

至于应该使用哪个,视情况而定。如果您希望您的委托更多地由它接受和返回的内容来定义,那么通用委托是完美的。如果您希望代理有一些特殊的名称,可以更详细地定义代理应该做什么(除了简单的ActionPredicate 等),那么创建自己的代理始终是一种选择。

【讨论】:

一个更清晰的例子是Func&lt;int, string&gt;,它表明表单是Func&lt;arg1, result&gt; 我认为值得注意的是 Func 和 Action 是代表。当您知道时,这似乎很明显,但是在查看 Func 的签名之前,我对这个事实感到害怕。所以当你说:“首先,你的两个例子在做两件完全不同的事情。”你也可以说:“Func 是一个代表”。【参考方案2】:

您拥有的代码示例有点令人困惑,所以让我试着把它弄清楚。以下 2 项是委托声明。这些很容易发现,因为它们总是包含 delegate 关键字

public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);

这行代码将一个值分配给一个输入到委托的本地

Func<string, string> local = lambda;

上面的代码不仅限于使用 lambdas。该值也可以是兼容的方法组或另一个委托值。

另外需要注意的一点是,尽管Func&lt;string, string&gt;convertMethod 都是具有相同签名的委托,但它们的值不可相互转换。例如以下是非法的

Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!

【讨论】:

【参考方案3】:

来自MSDN,

在 2.0 之前的 C# 版本中,声明委托的唯一方法是 使用命名方法。 C# 2.0 在 C# 中引入了匿名方法 3.0 及更高版本,lambda 表达式取代匿名方法作为 编写内联代码的首选方式。

在一种情况下,匿名方法提供了功能 在 lambda 表达式中找不到。匿名方法使您可以省略 参数列表。这意味着匿名方法可以 转换为具有各种签名的代表。

您可能也对delegate keyword vs lambda expression 上的这个 SO 回答感兴趣。

另外,MSDN 有一个good article on Lambda Expressions:

delegate int del(int i);
static void Main(string[] args)

    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25

在前面的示例中,请注意委托签名有一个 int 类型的隐式类型输入参数,并返回一个 int。这 lambda 表达式可以转换为该类型的委托,因为 它还有一个输入参数 (x) 和一个返回值 编译器可以隐式转换为 int 类型。 (类型推断是 在以下各节中更详细地讨论。)当代表 使用输入参数 5 调用,它返回结果 25.

【讨论】:

你也可以省略 lambda 中的参数。 ()=>Console.Writeline("参数少 lambda") 动作测试 = () =>Console.Writeline("parameter less lambda"); test.Invoke();【参考方案4】:

A 初始化委托的一个实例(可以立即调用)。它是一个 Func 类型的变量。

B 指定委托的定义(其签名)。以后可以用它来定义convertMethod类型的变量。

【讨论】:

以上是关于Func<string,string> 和委托有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何从属性名称创建 Expression<Func<TModel, string>> 表达式

逆变和协变 in,out有关

逆变和协变 in,out有关

表达式<Func<TModel,string>> 到表达式<Action<TModel>> “Getter” 到 “Setter”

使用 Func<T, string> lambda 动态构造 where 子句 - linq 到实体

Action 和 Func 的用法以及区别