C# 淺談委託----溫故而知新

 

先看看委託的概述:編程

 

•委託相似於 C++ 函數指針,但它們是類型安全的。windows

• 委託容許將方法做爲參數進行傳遞。安全

• 委託可用於定義回調方法。ide

• 委託能夠連接在一塊兒;例如,能夠對一個事件調用多個方法。函數

•方法沒必要與委託簽名徹底匹配。 有關更多信息,請參見 在委託中使用變體(C# 和 Visual Basic)。ui

• C# 2.0 版引入了匿名方法的 概念,此類方法容許將代碼塊做爲參數傳遞,以代替單獨定義的方法。 C# 3.0 引入了 Lambda 表達式,利用它們能夠更簡練地編寫內聯代碼塊。 匿名方法和 Lambda 表達式(在某些上下文中)均可編譯爲委託類型。 這些功能統稱爲匿名函數。 有關 lambda 表達式的更多信息,請參見 匿名函數(C# 編程指南)。this

 

委託是一種定義方法簽名的類型。 當實例化委託時,您能夠將其實例與任何具備兼容簽名的方法相關聯。 您能夠經過委託實例調用方法。spa

 

委託用於將方法做爲參數傳遞給其餘方法。 事件處理程序就是經過委託調用的方法。 您能夠建立一個自定義方法,當發生特定事件時某個類(例如 Windows 控件)就能夠調用您的方法。 .net

 

例子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);
        }
    }

 

而後再看看以上代碼又輸出什麼?

相關文章
相關標籤/搜索