程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 泛型委托使用,泛型委托

泛型委托使用,泛型委托

編輯:C#入門知識

泛型委托使用,泛型委托


泛型委托基礎

 

class Program  

class Program  
{  
        // 泛型委托,與普通委托類似,不同之處只在於使用泛型委托要指定泛型參數          
        public delegate T MyGenericDelegate<T>(T obj1,T obj2);  
  
        int AddInt(int x, int y)  
        {  
            return x + y;  
        }  
  
        string AddString(string s1, string s2)  
        {  
            return s1 + s2;  
        }  
         
        static void Main(string[] args)  
        {  
            Program p = new Program();  
             
            MyGenericDelegate<int> intDel;  
            intDel = p.AddInt;  
            Console.WriteLine("int代理的值是{0}", intDel(100, 200));  
  
            MyGenericDelegate<string> stringDel;  
            stringDel = p.AddString;  
            Console.WriteLine("string代理的值是{0}", stringDel("aaa", "bbb"));  
        }  
}  

 

為了方便開發,.NET基類庫針對在實際開發中最常用的情形提供了幾個預定義好的委托,這些預定義委托用得很廣,比如在編寫lambda表達式和開發並行計算程序時經常要用到他們。

     .NET提供的泛型委托包括action和func

     感悟:對泛型委托基本屬於有點認識,但從來沒真正在項目中使用過,有時感覺沒有合適的場景應用,但看了artech兄的文章,我才明白,原來泛型委托真的可以做很多事情,而且效果往往是沒有使用委托所達不到的。

    Action<T> 泛型委托:封裝一個方法,該方法只采用一個參數並且不返回值。可以使用此委托以參數形式傳遞方法,而不用顯式聲明自定義的委托。該方法必須與此委托定義的方法簽名相對應。也就是說,封裝的方法必須具有一個通過值傳遞給它的參數,並且不能返回值。當然泛型委托不只是只能支持一個參數,它最多可以支持四個參數。  

   泛型委托與直接顯示聲明自定義委托的示例比較:

      1:顯示聲明自定義委托:

   

delegate void DisplayMessage(string message);
public class TestCustomDelegate
{
   public static void Main()
   {
      DisplayMessage messageTarget; 
      messageTarget = ShowWindowsMessage;
      messageTarget("Hello, World!");   
   }      
   private static void ShowWindowsMessage(string message)
   {
      MessageBox.Show(message);      
   }
}

 2: Action<T> 用法。比起自定義委托,明顯可以看出代碼簡潔了。

public class TestAction1
{
   public static void Main()
   {
      Action<string> messageTarget; 
     messageTarget = ShowWindowsMessage;
      messageTarget("Hello, World!");   
   }      
   private static void ShowWindowsMessage(string message)
   {
      MessageBox.Show(message);      
   }
}

 Func<T, TResult> 委托:封裝一個具有一個參數並返回 TResult 參數指定的類型值的方法。同理,這裡的泛型委托只是接受一個參數的委托,它最多同樣支持四個參數。TResult:此委托封裝的方法的返回值類型。

問題:目前本公司在寫程序時,都使用了log4net,我想大家在做異常時,都會利用try catch來捕獲異常,日志就在catch塊中完成,但每個方法都寫一堆的try catch往往顯的有點別扭。雖然寫程序時提倡盡量去捕獲具體的錯誤異常,但總會有你預想不到的異常拋出,為此直接捕獲Exception算是不錯的做法。

    具體場景:在客戶端調用WCF服務時,我們都需要在客戶做異常處理,最常見的錯誤異常為CommunicationException,TimeoutException,Exception示例如下:

try
            {
                //執行方法調用 
                ......
                (proxy as ICommunicationObject).Close();
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();

                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常CommunicationException:" + ex.ToString());
            }
            catch (TimeoutException ex)
            {
                (proxy as ICommunicationObject).Abort();
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據超時TimeoutException:" + ex.ToString());
            }
            catch (Exception ex)
            {      
                (proxy as ICommunicationObject).Close();      
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常Exception:" + ex.ToString());
            }

 但如果這種代碼遍布整個項目,我想就有重構的必要了,因為項目中最好不要出現類似復制的代碼出現,為此我們可以采用Invoke形式來重構我們已有代碼,下面給出兩個方法,一個是沒有返回值的,一個是有值的。

public static void Invoke<TContract>(TContract proxy, Action<TContract> action)
        {
            try
            {
                action(proxy);
                (proxy as ICommunicationObject).Close();
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常CommunicationException:" + ex.ToString());
            }
            catch (TimeoutException ex)
            {
                (proxy as ICommunicationObject).Abort();
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據超時TimeoutException:" + ex.ToString());
            }
            catch (Exception ex)
            {        
                (proxy as ICommunicationObject).Close();      
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常Exception:" + ex.ToString());
            }
        }
        public static TReturn Invoke<TContract, TReturn>(TContract proxy, Func<TContract, TReturn> func)
        {
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy);
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();

                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常CommunicationException:" + ex.ToString());
            }
            catch (TimeoutException ex)
            {
                (proxy as ICommunicationObject).Abort();

                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據超時TimeoutException:" + ex.ToString());
            }
            catch (Exception ex)
            {
                WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數據異常Exception:" + ex.ToString());
            }
            return returnValue;
        }

  如何調用:可以看出客戶端代碼已經變成一條簡潔代碼了,它即完成了完整的異常處理,而且也把所有能夠捕獲的異常信息記錄下來。

list = ErrorHandler.Invoke<ISearchHotelForSquare, List<HotelGenericInfo>>(cli, proxy => proxy.GetHotelGenericListForSquare(requestInfo).ToList()); 

--此文章根據網絡資源整理.純屬個人筆記,別無其它商業用途.

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