zoukankan      html  css  js  c++  java
  • C# 浅谈委托----温故而知新

    先看看委托的概述:

    •委托类似于 C++ 函数指针,但它们是类型安全的。

    • 委托允许将方法作为参数进行传递。

    • 委托可用于定义回调方法。

    • 委托可以链接在一起;例如,可以对一个事件调用多个方法。

    •方法不必与委托签名完全匹配。 有关更多信息,请参见 在委托中使用变体(C# 和 Visual Basic)。

    • C# 2.0 版引入了匿名方法的 概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。 匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。 这些功能统称为匿名函数。 有关 lambda 表达式的更多信息,请参见 匿名函数(C# 编程指南)。

     

    委托是一种定义方法签名的类型。 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。 您可以通过委托实例调用方法。

     

    委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。 

    例子1:

        class Program
        {
    
            static void Main(string[] args)
            {
                Hello();
            }
    
            static void Hello()
            {
                System.Console.WriteLine("Hello, Delegate!");
            }
        }

    这是一个常见的方法, 输出一段字符串Hello, Delegate!

    下面我们来把他写成委托,

        class Program
        {
            delegate void PrintHello();
    
            static void Main(string[] args)
            {
                PrintHello ph = new PrintHello(Hello);
                ph.Invoke();
            }
    
            static void Hello()
            {
                System.Console.WriteLine("Hello, Delegate!");
            }
        }

    这里的PrintHello的方法类型需要和Hello保持一直,另外参数也需要保持一致,现在是无参数的.讲Hello作为参数传到委托中,然后用Invoke调用.
    以上代码也会输出,Hello, Delegate!因为invoke了这个方法.

    从.net 2.0开始就使用匿名委托, 可以这样申明

    delegate { };

    或者带参数的

    delegate (string i){ };

    {}括号中可以写需要执行的逻辑代码.

    有了匿名委托我们就可以偷一下懒了,可以把上面的例子改成如下:

        class Program
        {
            delegate void PrintHello();
    
            static void Main(string[] args)
            {
                PrintHello ph = delegate 
                { 
                    System.Console.WriteLine("Hello, Delegate!"); 
                };
                ph.Invoke();
    
            }
    
            //static void Hello()
            //{
            //    System.Console.WriteLine("Hello, Delegate!");
            //}
        }


    在.net 3.0中新加了Action<T> 无返回的委托, Predicate<T>有返回值,且返回true或false的委托.

    我们可以将上面的例子改成有参数的,

        class Program
        {
            static Action<string> print = delegate(string i) { System.Console.WriteLine("Hello, {0}!",i); };
    
            static void Main(string[] args)
            {
                print.Invoke("Delegate");
            }
        }

    或者用lambda表达式替代匿名委托,进一步偷懒..

        class Program
        {
            static Action<string> print = (i)=>{ System.Console.WriteLine("Hello, {0}!",i); };
    
            static void Main(string[] args)
            {
                print.Invoke("Delegate");
            }
        }

    以上会输出Hello,Delegate!因为将Delegate传入到最后输出.

    再来讲解一下Predicate这个只返回true or false的委托,如下:

        class Program
        {
            static Predicate<string> print = (i) => { return string.IsNullOrEmpty(i); };
            
            static void Main(string[] args)
            {
                System.Console.WriteLine(print.Invoke("Hello, Delegate!"));
            }
        }

    以上代码会输入true因为i不是为null or empty.

    在.net 3.5中又新加了Action(无返回值的委托,类似于delegate void)和Func<T,T> 带返回参数的,参数类型是T,返回类型也可以是int,string等..

    所以刚才的无参数的例子又可以写成这样:

        class Program
        {
            static Action print = () => { System.Console.WriteLine("Hello, Delegate!"); };
    
            static void Main(string[] args)
            {
                print.Invoke();
            }
        }


    再来看看Func<T,TReslut> 第一个T代表参数的类型,第一个TReslut代表返回结果的类型。

    如下,参数的类型是int,返回的类型是string.

        class Program
        {
            static Func<int,string> print = (i) => { return "Hello, Delegate!"+i.ToString(); };
            
            static void Main(string[] args)
            {
                System.Console.WriteLine(print.Invoke(0));
            }
        }

    输出的结果是:Hello, Delegate!0

    再来看看委托的回调函数,如下:

        class Program
        {
            delegate string callback(string firstName, string lastName);
    
            static void Main(string[] argss)
            {
                DoCallback("Charlie", "Wang", en_US);
                DoCallback("Tom", "Chen", ch_ZN);
    
            }
    
            static void DoCallback(string firstName, string lastName, callback call)
            {
                string result=call(firstName, lastName);
                Console.WriteLine(result);
            }
    
            static string en_US(string firstName, string lastName)
            {
                return firstName + " ," + lastName;
            }
    
            static string ch_ZN(string firstName, string lastName)
            {
                return lastName+", "+firstName;
            }
        }

    输出的结果为:

    Charlie ,Wang
    Chen, Tom

    我们还可以将以上代码进一步精简,用Func代替.

        class Program
        {
            static void Main(string[] argss)
            {
                DoCallback("Charlie", "Wang", en_US);
                DoCallback("Tom", "Chen", ch_ZN);
    
            }
    
            static void DoCallback(string firstName, string lastName, Func<string,string,string> callback)
            {
                string result = callback(firstName, lastName);
                Console.WriteLine(result);
            }
    
            static string en_US(string firstName, string lastName)
            {
                return firstName + " ," + lastName;
            }
    
            static string ch_ZN(string firstName, string lastName)
            {
                return lastName+", "+firstName;
            }
        }

    我们还可以这样写.

        class Program
        {
            static void Main(string[] argss)
            {
                DoCallback("Charlie", "Wang", en_US);
                DoCallback("Tom", "Chen", ch_ZN);
                DoCallback("Kevin", "Liu", (lastName, firstName) => { return string.Format("This is {0} {1}", lastName, firstName);});
            }
    
            static void DoCallback(string firstName, string lastName, Func<string,string,string> callback)
            {
                string result = callback(firstName, lastName);
                Console.WriteLine(result);
            }
    
            static string en_US(string firstName, string lastName)
            {
                return firstName + " ," + lastName;
            }
    
            static string ch_ZN(string firstName, string lastName)
            {
                return lastName+", "+firstName;
            }
        }

    输出结果为:

    Charlie ,Wang
    Chen, Tom
    This is Kevin Liu

    委托在很多时候使用可以精简我们的代码,看起来比较直观,下面是个很经典的案例:

        class Program
        {
            static void Main(string[] args)
            {
                B b = new B();
            }
        }
        class A
        {
            public A()
            {
                Print();
            }
            public virtual void Print() { }
        }
    
        class B : A
        {
            int x = 1;
            int y;
    
            public B()
            {
                y = -1;
            }
            public override void Print()
            {
                System.Console.WriteLine("x={0},y={1}", x, y);
            }
        }

    各位读者看看以上代码输出什么?

        class Program
        {
            static void Main(string[] args)
            {
                B b = new B();
                b.print();
            }
        }
        class A
        {
            public A()
            {
                Print();
            }
            public virtual void Print() { }
        }
    
        class B : A
        {
            int x = 1;
            int y;
            public Action print = delegate { };
    
            public B()
            {
                y = -1;
                this.print = Print;
            }
            public override void Print()
            {
                System.Console.WriteLine("x={0},y={1}", x, y);
            }
        }

    然后再看看以上代码又输出什么?



     

  • 相关阅读:
    poj 1611 The Suspects
    POJ 2236 Wireless Network
    POJ 1703 Find them, Catch them
    poj 1733 Parity game
    hdu 1598 find the most comfortable road
    cmake的使用二:链接第三方静态库
    线段树基础
    迪杰斯特拉算法
    Floyd详解
    STL中的set使用方法详细
  • 原文地址:https://www.cnblogs.com/fengqingyangNo1/p/3409424.html
Copyright © 2011-2022 走看看