C# 委托

2866人阅读 2022/2/9 11:18 总访问:652175 评论:0 收藏:0 手机
分类: .net

C# Func<>委托

   委托是一种类型,由关键字delegate声明。确切的说,委托是一种可用于封装命名或者匿名方法的引用类型。  它类似于 C++ 中的函数指针,而且是类型安全和可靠的。

  委托类型的声明与方法签名相似,有一个返回值和任意数目任意类型的参数。必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。下面给出了委托声明及实例化的示例代码:

原先我们定义delegat

// 委托声明 -- 定义一个签名:  
delegate double MathAction(double num);  
class DelegateTest  
{  
    // 符合委托声明的常规方法  
    static double Double(double input)  
    {  
        return input * 2;  
    }  
   
    static void Main()  
    {  
      // 使用一个命名方法实例化委托类型  
        MathAction ma = Double;  
   
        // 调用委托实例  
        double multByTwo = ma(4.5);  
        Console.WriteLine(multByTwo);  
   
     // 再用匿名方法来实例化委托类型  
        MathAction ma2 = delegate(double input)  
        {  
            return input * input;  
        };  
   
        double square = ma2(5);  
        Console.WriteLine(square);  
   
      // 最后用Lambda表达式来实例化委托类型  
        MathAction ma3 = s => s * s * s;  
        double cube = ma3(4.375);  
   
        Console.WriteLine(cube);  
    }  
}

.NETFramework 3.5中,提供了两类通用的delegate

如果方法有返回值,则使用Func,或者Func<>

如果方法没有返回值,则使用Action,或者Action<>

Func<T,TR>(T arg)

参数类型

T

此委托封装的方法的参数类型。

TR

此委托封装的方法的返回值类型。

 

参数

  • arg

  • 类型 T

  •  

  • 此委托封装的方法的参数。


 

 

在使用 Func<T,TResult>委托时,不必显式定义一个封装只有一个参数的方法的委托。以下示例简化了此代码,它所用的方法是实例化 Func<T, TResult>委托,而不是显式定义一个新委托并将命名方法分配给该委托。

 

使Func<>委托,我们这样写

  using System; 
  public class GenericFunc  {
    public static void Main()   { 
         // 依旧是用命名方法实例化委托类型  
           Func<string, string> convertMethod = UppercaseString;  
              string name = "Dakota";    // 依旧是通过委托实例调用该方法 
                Console.WriteLine(convertMethod(name));
                 } 
                   private static string UppercaseString(string inputString)
                   { 
                         return inputString.ToUpper(); 
                           }
                           }

您也可以按照以下示例所演示的那样在 C# 中将 Func<T, TResult> 委托与匿名方法一起使用。

  using System; 
 public class Anonymous 
 { 
   public static void Main()
    {
       Func<string, string> convert = delegate(string s) 
           { return s.ToUpper();}; 
              string name = "Dakota";
                  Console.WriteLine(convert(name));  
                   } 
                   }

 

您还可以按照以下示例所演示的那样将 lambda 表达式分配给 Func<T, TResult> 委托。

 using System;
 public class LambdaExpression 
 { 
   public static void Main()  
     { 
       Func<string, string> convert = s => s.ToUpper(); 
        string name = "Dakota";
         Console.WriteLine(convert(name)); 
           }
           }

Lambda 表达式的基础类型是泛型 Func 委托之一。  这样能以参数形式传递 lambda 表达式,而不用显式将其分配给委托。  尤其是,因为 System.Linq 命名空间中许多类型方法具有 Func<T, TResult> 参数,因此可以给这些方法传递 lambda 表达式,而不用显式实例化 Func<T, TResult> 委托。

 

Func委托是system下的全局函数,不用我们自定,系统自定义的,供我们使用,带有多个重载.

这里我们除了使用Func委托外,还是用了Labdab表达式.这里我再谈谈这个表达式.

Lambda表达式的基础类型是泛型 Func委托之一。 这样能以参数形式传递 lambda表达式,而不用显式将其分配给委托。 尤其是,因为 System.Linq命名空间中许多类型方法具有Func<T, TResult>参数,因此可以给这些方法传递 lambda表达式,而不用显式实例化 Func<T, TResult>委托。

 

如果前面的解析看的不是很清楚,相信最后这个实例能够让你更加明白Func委托是多么有意思。

下面的示例演示如何声明和使用 Func<T, TResult> 委托。  此示例声明一个 Func<T, TResult> 变量,并为其分配了一个将字符串中的字符转换为大写的 lambda 表达式。  随后将封装此方法的委托传递给 Enumerable.Select方法,以将字符串数组中的字符串更改为大写。

 
  using System; 
   using System.Collections;  
    using System.Collections.Generic;  
     using System.Linq;  
      static class Func  
       { 
           static void Main(string[] args) 
              { 
                   // 声明了一个Func委托类型的变量selector并用Lambda表达式进行实例化  
                       // 这个Lambda表达式将用来获取一个字符串并将这个字符串转化为大写并返回 
                           Func<string, string> selector = str => str.ToUpper();
                              // 创建一个字符串数组 
                                    string[] words = { "orange", "apple", "Article", "elephant" }; 
                                       // 依次遍历这个字符串数组并调用委托实例selector进行处理 
                                        IEnumerable<String> aWords = words.Select(selector); 
                                        
                                           // 输出结果到控制台 
                                           foreach (String word in aWords) 
                                             Console.WriteLine(word); 
                                               } 
                                               }   
                                                /* 
                                                 This code example produces the following output:
                                                   ORANGE 
                                                     APPLE
                                                        ARTICLE
                                                           ELEPHANT 
                                                            */

通过委托和Lambda表达式及Func<>特性的结合,可以看出他们带给代码多么大的改变,不仅让我们的代码更加简洁,更让我们的代码执行起来更加高效灵活。

 

三种委托写法对比

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
   
namespace func  
{  
//委托声明 -- 定义一个签名:  
delegate double MathAction(double num);  
public class Program  
{  
// 符合委托声明的常规方法  
static double Double(double input)  
{  
return input * 2;  
}  
   
static void Main(string[] args)  
{  
// 使用一个命名方法实例化委托类型  
/* 
 * 写法一,需要写出专门委托的函数,还需要自定义委托 
 **/  
MathAction ma = Double;//注意这里千万不可有Double(),否则就成了一个返回类型,是报错的,这里是制定函数的地址,给定的是函数的地址  
   
//调用委托  
double result1 = ma(4.5);  
   
//使用系统自定义委托实例化委托类型  
/* 
 * 写法二,需要写出专门委托的函数,不需要自定义委托,使用系统委托 
 **/  
Func<double,double> func = Double;  
   
//调用委托  
double result2 = func(4.5);  
   
//系统委托使用lamdba进行传递参数  
/* 
 * 写法三,不需要写出专门委托的函数,还需要自定义委托 
 **/  
Func<double, double> result = s=> s * 2;//写法还可以换成lamdba语句块,适应多个参数的写法  
   
double result3=result(4.5);  
   
Func<double,double> result4 = s =>  
{  
return s * 2;  
};  
   
Console.WriteLine(result1);  
Console.WriteLine(result3);  
Console.WriteLine(result2);  
Console.WriteLine(result4(4.5));  
}   
}
  }


效果图

 

同样的输出效果,但是编写代码的质量确有不同。Func的委托中,它简化了我们自己定义委托带来的繁琐,同时它更好的结合了Lamdba的使用,减少了自定义函数的作用,同时也是有缺点的,就是错误的出现不容易发现是那里。如果不是对这个很熟悉,很容易造成出现问题,如从着手错误的源泉。匿名函数的写法解决的这个问题。但是匿名函数却没有Lamdba简便。Action委托的使用与Func雷同。
原:C# Func<>委托 - gxwzwyq - 博客园 (cnblogs.com)


评价
脚踏实地,一步一个脚印
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
欢迎加群交流技术