程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 編寫高質量代碼改善C#程序的157個建議[C#閉包的陷阱、委托、事件、事件模型]

編寫高質量代碼改善C#程序的157個建議[C#閉包的陷阱、委托、事件、事件模型]

編輯:C#入門知識

前言

本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要學習記錄以下內容:

  建議38、小心閉包中的陷阱

  建議39、了解委托的實質

  建議40、使用event關鍵字對委托施加保護

  建議41、實現標准的事件模型

建議38、小心閉包中的陷阱

  首先我們先來看一段代碼:

    class Program
    {
        static void Main(string[] args)
        {
            List<Action> list = new List<Action>();
            for (int i = 0; i < 5; i++)
            {
                Action t = () =>Console.WriteLine(i.ToString());
                list.Add(t);
            }
            foreach (Action t in list)
            {
                t();
            }
                Console.ReadLine();
        }
    }

你設想的結果或許是0,1,2,3,4

但沒想到執行後結果如下

通過IL可以查看代碼,組合後大致代碼如下:

    public class TempClass
    {
        public int i;
        public void TempFunc()
        {
            Console.WriteLine(i.ToString());
        }

    } 
    class Program
    {
        static void Main(string[] args)
        {
            List<Action> list = new List<Action>();
            TempClass tempClass = new TempClass();
            for (tempClass.i = 0; tempClass.i < 5; tempClass.i++)
            {
                Action t = tempClass.TempFunc;
                list.Add(t);
            }
            foreach (Action t in list)
            {
                t();
            }
                Console.ReadLine();
        }
    }

當然運行後結果還是5,5,5,5,5

其實這段代碼所演示的就是一個閉包對象。所謂的閉包對象,指的是上面這種情形中的TempClass對象,如果匿名方法(Lambda表達式)引用了某個局部變量,編譯器就會自動將該引用提升到該閉包對象中,即將for循環中的變量i修改成了引用閉包對象的公共變量i。這樣一來,即使代碼執行後離開了原局部變量i的作用域(如for循環),包含該閉包對象的作用域也還存在。

下面簡單修改一下之前的代碼

    class Program
    {

        static void Main(string[] args)
        {
            List<Action> list = new List<Action>();
            for (int i = 0; i < 5; i++)
            {
                int temp = i;
                Action t = () => Console.WriteLine(temp.ToString());
                list.Add(t);
            }
            foreach (Action t in list)
            {
                t();
            }
            Console.ReadLine();
        }
    }

執行結果如下:

建議39、了解委托的實質

 http://www.cnblogs.com/aehyok/archive/2013/03/22/2976356.html這裡有我之前對委托的簡單的學習過程,雖然在工作中很少用,幾乎就沒用。不過還是拿來學習學習。

 理解委托需要把握兩個點:

1、委托是方法指針。

2、委托就是一個類。當對其進行實例化的時候,要將引用方法作為它構造函數的參數。

建議40、使用event關鍵字對委托施加保護

 http://www.cnblogs.com/aehyok/archive/2013/02/22/2922586.html 這也是對於事件的簡單理解學習。

建議41、實現標准的事件模型

我們應該知道微軟為事件模型設定的幾個規范:

1、委托類型的名稱以EventHandler結束。

2、委托原型返回值為void。

3、委托原型具有兩個參數:sender表示事件觸發者,e表示事件參數。

4、事件參數的名稱以EventArgs結束。

    public class FileUploadedEventArgs : EventArgs
    {
        public int FileProgress { get; set; }
    }

    public class FileUploader
    {
        public event EventHandler<FileUploadedEventArgs> FileUploaded;

        public void Upload()
        {
            FileUploadedEventArgs e = new FileUploadedEventArgs() { FileProgress=100 };
            while (e.FileProgress > 0)
            {
                ///傳輸代碼,省略
                e.FileProgress--;
                if (FileUploaded != null)
                {
                    FileUploaded(this, e);
                }
            }
        }
    }

最終進行調用的代碼如下:

    class Program
    {
        static void Main(string[] args)
        {
            FileUploader fileUploader = new FileUploader();
            fileUploader.FileUploaded += Progress;
            fileUploader.Upload();
            Console.ReadLine();
        }

        static void Progress(object sender,FileUploadedEventArgs e)
        {
            Console.WriteLine(e.FileProgress);
        }
    }

 

 

英語小貼士

1、Hello. This is United Airlines.——聯合航空,您好。  I'd like to reconfirm my flight.——我想要再確認班機。

2、What's your name and flight number?——請說您的大名與班機號碼?  

3、My name is Jerry Cheng, and the flight number is UA 003 for Los Angeles.——我的名字是傑瑞‧陳,班機號碼是飛往洛杉機的聯合航空003班機。

4、When is it?June 10th.——行程是那一天?6月10日。

5、I'd like to make sure of the time it leaves.——我想要確認班機時間沒有改變。

6、I can't find your name. Really?——我找不到您的大名。真的?  May I have your name again?——請再告訴我一次您的大名?

7、I still can't find your name on the reservation list.——我仍然無法在訂位名單中找到您的名字。

8、Anyway, we have seats for new bookings on this flight. No problem.——別擔心,這班班機仍有空位提供新的訂位者。

9、One economy class seat, is that right?——一個經濟艙座位,對嗎?  Now you have been booked.——沒問題,您已完成訂位。

10、Thanks a lot. What time do you start check-in?——謝謝。你們何時開始辦理登機?

11、Two hours before departure time.——起飛前2小時。  You must check-in at least one hour before.——你必須在至少1小時前辦理登機。

作者:aehyok

出處:http://www.cnblogs.com/aehyok/

感謝您的閱讀,如果您對我的博客所講述的內容有興趣,那不妨點個推薦吧,謝謝支持:-O。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved