• 托付具体解释


    托付

    为什么要使用托付:

             我们习惯性的把数据当做參数传递给方法。假设给方法传递一个方法呢?可是往往有时候我们要给一个方法传递还有一个方法。

    更麻烦的是,有时候我们并不知道程序在编译时才知道应该传递哪一个方法。

    可是.NET Framework语法是不同意直接调用方法的,必须把方法的细节封装在一种新类型的对象中。这个新类型就是托付。

    keyword是delegate。托付是一个特殊的类型对象。其特殊之处在于。我们曾经定义的对象包括的是数据。可是托付保护哈韩的仅仅是一个方法或多个方法的地址。

    与托付相关的类与keyword(假设不想知道语言怎样实现的。就先跳过这一部分,看完详细实现。再来看看C#是怎样实现的)

    Delegate类:

    Delegate 类是托付类型的基类。 然而,仅仅有系统和编译器能够显式地从Delegate 类或 MulticastDelegate 类派生。此外。还不同意从托付类型派生新类型。

    Delegate 类不是托付类型,该类用于派生托付类型。

    大多数语言实现 delegate keyword,这些语言的编译器可以从 MulticastDelegate 类进行派生;所以,用户应当使用语言所提供的 delegate keyword。

    公共语言执行时为每一个托付类型提供 Invoke 方法(使用与该托付同样的签名)。不必从 C#、Visual Basic 或 Visual C++ 显式调用此方法,由于编译器将自己主动调用此方法。须要查找托付类型的签名时 Invoke 方法在反射 上非常实用。

    托管语言使用 Combine 和 Remove 方法实现托付操作。

    演示样例包含 Visual Basic 中的 AddHandler 和 RemoveHandler 语句以及 C# 中托付类型上的 += 和 -= 运算符。

    怎样使用托付

    以下这个样例有三种托付的用法;

    首先要定义一个托付:没有public delegate string GetString();

    第一种直接把系统方法绑定到托付上:

    GetString g = new GetString(i.ToString);

    g();

    另外一种:把系统方法ToString()托付给GetString

    GetString g = i.ToString;

    g();

    第三种:通过结构体进行托付。

    g = new GetString(c.GetCurrency);

    g();

    class Program
        {
            //定义一个没有參数,返回值为string 类型的托付。

    //define delegate no parameter and return string public delegate string GetString(); static void Main(string[] args) { int i = 40; //直接把系统方法ToString()托付给GetString // GetString g = new GetString(i.ToString); //使用还有一种方法把系统方法ToString()托付给GetString GetString g = i.ToString; Console.WriteLine( "string is "+ g() ); //通过结构体使用托付 Currency c = new Currency(34, 50); g = c.ToString; Console.WriteLine("string is " + g()); g = new GetString(c.GetCurrency); Console.WriteLine("string is " + g()); Console.ReadKey(); } } struct Currency { public uint Dollars; public ushort Cents; public Currency(uint Dollars,ushort Cents) { this.Dollars = Dollars; this.Cents = Cents; } public override string ToString() { return string.Format("${0}.{ 1,2:00}",this.Dollars,this.Cents); } public string GetCurrency() { return "Dollar"; } public static explicit operator Currency(float value) { //checked是什么意思。 checked { uint dollars=(uint )value ; ushort cents = (ushort)((value - dollars) * 100); return new Currency(dollars,cents); } } //对float类型进行重载。

    public static implicit operator float (Currency value) { return value.Dollars+(value.Cents/100.0f); } //对Currency类型进行重载 public static implicit operator Currency (uint value) { return new Currency(value, 0); } //对uint类型进行重载。。 public static implicit operator uint(Currency value) { return value.Dollars; } }


    假设你是一个合格的程序猿,请认真思考程序中一下三个问题:

    1、  checkedkeyword是干嘛用的?

    2、  还有结构体最后三个函数是什么意思?(点击获得答案。

    3、  string.Format("${0}.{ 1,2:00}",this.Dollars,this.Cents);当中${0}.{1,2:00}怎样实现的?

    第二个实例:

    以下这个样例。只使用托付来调用两个不同的操作。它说明了怎样把托付传递给方法。怎样使用托付数组。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TestDelegateSimple
    {
        delegate double DoubleOp(double value);
        class Program
        {
            static void Main(string[] args)
            {
                DoubleOp[] options = { MathOptions.MultiplyTwo, MathOptions.Square};
                for (int i = 0; i < options.Length; i++)
                {
                    Console.WriteLine("using option[{0}]",i);
                    ProcessAndDisplayNumber(options[i], 2.0);
                    ProcessAndDisplayNumber(options[i], 7.94);
                    ProcessAndDisplayNumber(options[i], 1.414);
                }
                Console.ReadKey();
            }
            private static void ProcessAndDisplayNumber(DoubleOp d,double value)
            {
                double d1 = d(value);
                Console.WriteLine("value is {0}。result of option is {1}",value,d1);
            }
        }
        class MathOptions
        {
            public static double MultiplyTwo(double value)
            {
                return value * 2;
            }
            public static double Square(double value)
            {
                return value * value;
            }
        }
        
    }
    
    

    多播托付:

    前面使用的都是包括一个方法的调用,假设想调用多个方法。就须要多次显示调用这个托付,也能够包括多个方法。这样的成为托付多播。

    把上一个样例改为多播的情况:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DuoBoDelegate
    {
        class Program
        {
            static void Main(string[] args)
            {
               Action <double >options = MathOptions.MultiplyTwo;
               options+=MathOptions.Square;
               
                    ProcessAndDisplayNumber(options, 2.0);
                    ProcessAndDisplayNumber(options, 7.94);
                    ProcessAndDisplayNumber(options, 1.414);
                Console.ReadKey();
            }
            private static void ProcessAndDisplayNumber(Action<double> d, double value)
            {
                Console.WriteLine();
                Console.WriteLine("value is {0},result of option is", value);
                d(value);
            }
        }
        class MathOptions
        {
            public static void MultiplyTwo(double value)
            {
                double result = value * 2;
                Console.WriteLine("MutiplyTwo by 2:{0} give {1}",value,result);
            }
            public static void Square(double value)
            {
                double result = value * value;
                Console.WriteLine("MutiplyTwo by 2:{0} give {1}", value, result);
            }
        }
    }
    
    

    第三个实例:

    托付泛型:Action<T>与Func<T>托付。

    除了上面的定义托付的方法还能够使用这两种方法定义托付。

    Action<T>:表示引用一个void返回类型的方法。Action<inT1>表示一个參数的没有返回的托付。Action<in T1,in T2>表示两个參数的没有返回的托付。

    Func<T>:表示引用一个有返回类型的方法。

    Func<inT1,out TResult>,表示一个參数的有返回值的參数。

    上一个样例仅仅是说明了托付的多种实现,并没有非常好的说明,没有托付不能实现这些方法。他有一个类BubbleSorter,该类实现了一个排序算法,没有托付非常难编写这个类。

    这个类能够排序不论什么一种类型。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace BobbleSorter
    {
        class Program
        {
            static void Main(string[] args)
            {
                Employee[] employee = { 
                                      new Employee("jack",1220),
                                      new Employee("jason",2),
                                      new Employee("jonee",2999),
                                      new Employee("alvin",100),
                                      };
                BubbleSorter.Sort(employee, Employee.CompareSalary);
                foreach (var item in employee)
                {
                    Console.WriteLine(item);
                }
                Console.ReadKey();
            }
        }
        //排序类
        #region Sorter Class
        class BubbleSorter
        {
            public BubbleSorter()
            {
    
            }
            public static void Sort<T>(IList<T> sortArray,Func<T,T,bool> comparsion)
            {
                bool swapped = true;
                do
                {
                    swapped = false;
                    for (int i = 0; i < sortArray.Count-1; i++)
                    {
                        if (comparsion(sortArray[i+1],sortArray[i]))
                        {
                            T temp = sortArray[i];
                            sortArray[i] = sortArray[i + 1];
                            sortArray[i + 1] = temp;
                            swapped = true;
                        }
                    }
                } while (swapped);
            }
        }
        #endregion
        //员工类
        #region Employee Class
        class Employee
        {
            private string name;
            private decimal salary;
    
            public decimal Salary
            {
                get { return salary; }
                set { salary = value; }
            }
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
           
            public Employee()
            { 
            
            }
            public Employee(string name,decimal salary)
            {
                this.name = name;
                this.salary = salary;
            }
            public override string ToString()
            {
                return string.Format("{0},{1:C}",this.name,this.salary);
            }
            public static bool CompareSalary(Employee e1, Employee e2)
            {
                return e1.Salary < e2.Salary;
            }
        }
        #endregion
    
    }
    

    思考:为什么类中方法public static void Sort<T>(IList<T>sortArray,Func<T,T,bool> comparsion)

    參数为什么是Ilist泛型集合,可是传入的一个数组?

    匿名方法:

    匿名方法就是使一段代码作为托付的參数。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace NiMingDelegate
    {
        class Program
        {
            static void Main(string[] args)
            {
                string mid = ",middle part,";
                Func<string, string> anonDel = delegate(string para)
                {
                    para += mid;
                    para += "and this is add the string";
                    return para;
                };
                Console.WriteLine(anonDel("Start of string"));
                Console.ReadKey();
            }
        }
    }
    

    对于上面的思考题有不会的,能够回复我。

    我给你解答》》》

  • 相关阅读:
    Android开发 GradientDrawable详解
    Android开发 ShapeDrawable详解
    Android开发 ViewPager删除Item后,不会更新数据和View
    Android开发 输入法调用学习
    Android开发 EditText的开发记录
    Android开发 TextView的开发记录
    Android开发 获取View的尺寸的2个方法
    Android开发 获取视频中的信息(例如预览图或视频时长) MediaMetadataRetriever媒体元数据检索器
    Android开发 Tablayout的学习
    Python 模块-zipfile
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6873569.html
Copyright © 2020-2023  润新知