【读书笔记】 泛型委托

       通过昨天的例子可以看到泛型类型实现IAccount接口的要求过于严厉。为了将Accumulate()方法改为泛型方法,还要去创建一个IAccount接口,然后让Account类继承IAccount接口,然后....杯具( ⊙ o ⊙ )啊! 在今天的例子中,我们可以创建独立于任何接口的泛型方法。这个就需要泛型委托机制来帮忙实现了。

 下面是修改后的泛型委托的例子

using System;

using System.Collections.Generic;

using System.Collections;

using System.Linq;

using System.Text;



namespace GenericMethod

{

    // 定义一个泛型委托

    // TInput是要累加的对象

    // TSummary是返回类型

    public delegate TSummary Action<TInput, TSummary>(TInput t, TSummary u);



    public class Account

    {

        private string name;

        public string Name

        {

            get

            {

                return name;

            }            

        }



        private decimal balance;

        public decimal Balance

        {

            get

            {

                return balance;

            }

        }



        public Account(string name, decimal balance)

        {

            this.name = name;

            this.balance = balance;

        }        

    }



    public static class Algorithm

    {

        // 使用委托的泛型方法

        public static TSummary Accumulate<TInput, TSummary>(IEnumerable<TInput> coll, Action<TInput, TSummary> action)

        {

            TSummary sum = default(TSummary);



            foreach (TInput input in coll)

            {

                sum = action(input, sum);

            }



            return sum;

        }

    }



    class Program

    {

        static void Main(string[] args)

        {

            List<Account> accounts = new List<Account>();

            accounts.Add(new Account("Christian", 1500));

            accounts.Add(new Account("Sharon", 2200));

            accounts.Add(new Account("Katie", 1800));



            // 通过匿名方法调用

            //decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, delegate(Account a, decimal d){return a.Balance + d;});

            

            // 还可以通过λ表达式调用

            decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, (a, d) => a.Balance + d;);



            Console.WriteLine(amount.ToString());

            Console.ReadLine();



        }

    }

}



 

 

郁闷了,编译有个错误:

Error 1 ) expected E:\C Sharp\ComputerManager\GenericMethod\GenericMethod\Program.cs 70 102 GenericMethod
Error 2 Invalid expression term ')' E:\C Sharp\ComputerManager\GenericMethod\GenericMethod\Program.cs 70 103 GenericMethod
Error 3 Only assignment, call, increment, decrement, and new object expressions can be used as a statement E:\C Sharp\ComputerManager\GenericMethod\GenericMethod\Program.cs 70 102 GenericMethod

编译怎么出问题了,实在不解,待会儿查下。

NOTE:偶晕倒,原来是这里出问题了

 decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, (a, d) => a.Balance + d;);

应该是这样写,多了一个分号囧

 decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, (a, d) => a.Balance + d);

 

通过匿名方法调用的那个是没有任何问题的。

 

下面的这个就是标准的委托形式了,这个看不懂,就要回去看下委托的章节了。

using System;

using System.Collections.Generic;

using System.Collections;

using System.Linq;

using System.Text;



namespace GenericMethod

{

    // 定义一个泛型委托

    // TInput是要累加的对象

    // TSummary是返回类型

    public delegate TSummary Action<TInput, TSummary>(TInput t, TSummary u);



    public class Account

    {

        private string name;

        public string Name

        {

            get

            {

                return name;

            }            

        }



        private decimal balance;

        public decimal Balance

        {

            get

            {

                return balance;

            }

        }



        public Account(string name, decimal balance)

        {

            this.name = name;

            this.balance = balance;

        }        

    }



    public static class Algorithm

    {

        // 使用委托的泛型方法

        public static TSummary Accumulate<TInput, TSummary>(IEnumerable<TInput> coll, Action<TInput, TSummary> action)

        {

            TSummary sum = default(TSummary);



            foreach (TInput input in coll)

            {

                sum = action(input, sum);

            }



            return sum;

        }



        public static decimal AccountAdder(Account a, decimal d)

        {

            return a.Balance + d;

        }

    }



    class Program

    {

        static void Main(string[] args)

        {

            List<Account> accounts = new List<Account>();

            accounts.Add(new Account("Christian", 1500));

            accounts.Add(new Account("Sharon", 2200));

            accounts.Add(new Account("Katie", 1800));



            // 通过匿名方法调用

            //decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, delegate(Account a, decimal d){return a.Balance + d;});

            

            // 还可以通过λ表达式调用

            //decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, (a, d) => a.Balance + d;);



            // 使用标准的委托形式

            // 单独再写一个AccountAdder方法

            decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, Algorithm.AccountAdder);



            Console.WriteLine(amount.ToString());

            Console.ReadLine();



        }

    }

}



 

这样就很灵活了,你可以在Action方法里面想做什么就做什么,可以乘法除法都可以了。

 

下面再做一个扩展可以在Accumulate的时候加入一个委托应用来检查某个账目是否应累加进去。

using System;

using System.Collections.Generic;

using System.Collections;

using System.Linq;

using System.Text;



namespace GenericMethod

{

    // 定义一个泛型委托

    // TInput是要累加的对象

    // TSummary是返回类型

    public delegate TSummary Action<TInput, TSummary>(TInput t, TSummary u);



    public class Account

    {

        private string name;

        public string Name

        {

            get

            {

                return name;

            }            

        }



        private decimal balance;

        public decimal Balance

        {

            get

            {

                return balance;

            }

        }



        public Account(string name, decimal balance)

        {

            this.name = name;

            this.balance = balance;

        }        

    }



    public static class Algorithm

    {

        // 使用委托的泛型方法

        public static TSummary Accumulate<TInput, TSummary>(IEnumerable<TInput> coll, Action<TInput, TSummary> action)

        {

            TSummary sum = default(TSummary);



            foreach (TInput input in coll)

            {

                sum = action(input, sum);

            }



            return sum;

        }



        public static decimal AccountAdder(Account a, decimal d)

        {

            return a.Balance + d;

        }



        public static TSummary AccumulateIf<TInput, TSummary>(IEnumerable<TInput> coll, Action<TInput, TSummary> action, Predicate<TInput> match)

        {

            TSummary sum = default(TSummary);



            foreach (TInput a in coll)

            {

                if (match(a))

                {

                    sum = action(a, sum);

                }

            }

            return sum;

        }

    }



    class Program

    {

        static void Main(string[] args)

        {

            List<Account> accounts = new List<Account>();

            accounts.Add(new Account("Christian", 1500));

            accounts.Add(new Account("Sharon", 2200));

            accounts.Add(new Account("Katie", 1800));



            // 通过匿名方法调用

            //decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, delegate(Account a, decimal d){return a.Balance + d;});

            

            // 还可以通过λ表达式调用

            //decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, (a, d) => a.Balance + d);



            // 使用标准的委托形式

            // 单独再写一个AccountAdder方法

            // decimal amount = Algorithm.Accumulate<Account, decimal>(accounts, Algorithm.AccountAdder);



            // 新委托方法的调用

            decimal amount = Algorithm.AccumulateIf<Account, decimal>(accounts, (a, d) => a.Balance + d, a => a.Balance > 2000);



            Console.WriteLine(amount.ToString());

            Console.ReadLine();

        }

    }

}



 对Array类使用泛型方法

using System;

using System.Collections.Generic;

using System.Collections;

using System.Linq;

using System.Text;



namespace ArrayGenericDelegate

{

    public class Person

    {

        private string firstName;

        public string FirstName

        {

            get

            {

                return firstName;

            }            

        }



        private string lastName;

        public string LastName

        {

            get

            {

                return lastName;

            }

        }



        public Person(string firstname, string lastname)

        {

            this.firstName = firstname;

            this.lastName = lastname;

        }

    }



    public class Racer

    {

        public string Name

        {

            get;

            set;

        }



        public string Team

        {

            get;

            set;

        }



        public Racer(string name)

        {

            this.Name = name;

        }

    }





    class Program

    {

        static void Main(string[] args)

        {

            Person[] persons = {

            new Person("Emerson", "Fittipaldi"),

            new Person("Niki", "Lauda"),

            new Person("Ayrton", "Senda"),

            new Person("Michael", "Schumacher")

            };



            // 调用Array的Sort泛型方法给Person数组进行首姓名排序

            Array.Sort(persons, (p1, p2) => p1.FirstName.CompareTo(p2.FirstName));



            // 调用Array的Foreach泛型方法将Person数组的首姓名输出到控制台

            Array.ForEach(persons, p => Console.WriteLine("{0}", p.FirstName));

            // 调用Array的Foreach泛型方法将Person数组的末姓名输出到控制台

            Array.ForEach(persons, p => Console.WriteLine("{0}", p.LastName));



            // 调用Array的FindAll泛型方法查找首字母以S开头的Person类集合

            Person[] sPersons = Array.FindAll(persons, p => p.LastName.StartsWith("S"));



            // 调用Array的ConvetAll泛型方法将一种类型数组转换为另一种类型数组

            Racer[] racers = Array.ConvertAll<Person, Racer>(persons, p => new Racer(String.Format("{0} {1}", p.FirstName, p.LastName)));



            Console.ReadLine();

        }

    }

}



从上面的例子看出Array类的泛型方法还是很强大的。

 

你可能感兴趣的:(读书笔记)