Action<T>和Func<T>泛型委托,委托,泛型,匿名函数,Lambda表达式的综合使用

前言

在上篇文章C#中委托(delegate)和多播委托的理解中已经基本了解了委托的用法。
由于委托封装的方法我们不一定知道其传入的参数和返回值,例如之前说的的排序方法—————在对象的排序算法中,需要对对象进行比较,而不同对象比较的方法不同,所以比较两个对象的方法的引用可以作为参数传递到排序算法中,这个时候就需要传递方法。
当我们要生成一个封装比较对象的方法的委托时,我们并不知道该方法传入对象是什么,所有我们必须引入泛型的概念来辅助委托的使用。

Action<T>Func<T>泛型委托

除了为每个参数和返回类型定义一个新委托类型外(基本的委托定义方法),还有就是使用Action<T>Func<T>定义委托,Action<T>委托表示引用一个void返回类型的方法,且最多可以传递16种参数;Func<T>类似,但允许调用带返回值的方法。

注意对比普通委托泛型委托的定义和使用的区别。

普通委托的定义和使用的博客

泛型委托的定义和使用:
对于上篇加减的例子,可以直接将Func<int, int,int>类型的委托作为参数:

public int numMethod(int num1, int num2, Func<int, int,int> callback)
        {
            return callback(num1,num2);
        }

这两种方法的区别就在于,我们可以跳过普通委托声明委托对象的过程,其实我们通过查看元数据就可以看出,其时是框架给我们封装好了Func<int, int,int>方法,其实普通委托泛型委托并无太大区别:

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

在我们调用Func<int, int,int>方法是其实还是生成了一个委托对象,该委托封装的方法的参数和返回值的类型会自动设置为我们实例该委托的方法的参数和返回值,所以我们使用了来代表任意类型的参数和返回值;

总结

Action<T>Func<T>泛型委托普通委托,没有本质区别,普通委托是手动设置委托对象的参数和返回值,而泛型委托会根据我们传入的方法的参数和返回值自动设置其对应的委托对象;

由于Action<T>Func<T>相当于声明好的委托,我们调用它,只是给它实例化,所以不能和声明普通委托一样在类的外部调用!
更加具体的理解就是:

如果普通委托可以封装的具有相同类型参数和返回值的方法,而泛型委托可以封装的就是参数和方法值的类型具有相同对应关系的方法。

那么这样带来的好处有什么?
匿名方法

Lambda表达式
的使用
可以通过下面这个实例体现出来

重点

这个实例里泛型委托,匿名方法,Lambda表达式,泛型都有出现,是一个非常好的实例!还出现了另一种泛型委托———Comparison<in T>

class Program
    {
        static void Main(string[] args)
        {
            List<StudentScore> lst = new List<StudentScore>()//需要被排序的对象组
            {
                new StudentScore("A",50),
                new StudentScore("B",60),
                new StudentScore("C",70),
                new StudentScore("D",80),
                new StudentScore("E",93),
                new StudentScore("F",69),
                new StudentScore("G",36),
                new StudentScore("H",76),
                new StudentScore("I",66),
                new StudentScore("J",98)
            };
            //方法一:通过比较两个对象的匿名函数采用Lambda表达式,来声明该委托
            Func<StudentScore, StudentScore, bool> fun = (x, y) => x.score < y.score;
            //方法二:通过比较两个对象方法,声明该泛型委托
            //Func<StudentScore, StudentScore, bool> fun = compare;
            HighestScores(lst, fun);
            //方法三:直接将比较对象的方法传入
            //HighestScores(lst, compare);
            Console.ReadLine();

        }

        static public void HighestScores<T>(IList<T> sourceArray, Func<T, T, bool> comp)
        {
            int cnt = Convert.ToInt32((float)sourceArray.Count * 0.2);//前百分之二十
            List<T> lst = sourceArray.ToList();

            lst.Sort((x, y) => comp(x, y) == true ? 1 : -1);//Sort的一个重载参数为Comparison<T>泛型委托
            ///Sort的参数为一个类似于Func<>的表达式,这里给它赋的为一个Lambda表达式,
            ///当然这里也同上面的方法二一样可以将匿名方法抽取出来
            ///相当于Comparison<T> comparison=(x, y) => comp(x, y) == true ? 1 : -1;
            ///其中:
            ///public void Sort(Comparison<T> comparison);
            ///public delegate int Comparison<in T>(T x, T y);
            ///其中Comparison<in T>和前面的Func<>功能类似
            
            foreach (T t in lst.Take(cnt))//返回排序好对象组的前cnt个对象
                Console.WriteLine(t);
        }

        static public bool compare(StudentScore x ,StudentScore y)
        { 
            return x.score < y.score?true : false;
        }
    }

    class StudentScore
    {
        public StudentScore(string n, int s)
        {
            this.name = n;
            this.score = s;
        }

        public string name;
        public int score;

        public override string ToString()
        {
            return string.Format("{0} {1}", this.name, this.score);
        }
    }

事件(event)和委托(delegate)的综合运用实例(WinForm控件事件执行流程和原理),和EventHandler委托

猜你喜欢

转载自blog.csdn.net/define_LIN/article/details/83274704