C#中那些常用的工具類(Utility Class)(一)


  代碼越寫越多,但是我們也需要經常去反思那些寫過的代碼,Utility Class就是這一類需要特別去反思總結的類,這些類像工具一樣,我們經常通過一些靜態方法,通過傳入一些參數,然后得到我們需要的結果,在下面的一系列博客中,我們就一點一滴去反思這些類,並提供一個很好的方式去為他人提供方便,促進彼此之間的相互學習。  

  首先第一個介紹的就是ParseUtil這個靜態類,在我們的代碼中,我們經常需要去將string類型的字符串去做一個類型轉換,比如說int,double,demical,float,DateTime、short、long甚至是byte數組類型,當我們轉換失敗時還可以提供一個默認值,這些值能夠保證一定去返回這些正確的類型值。

  這組代碼的核心部分就是:  

private static T ParseStringToType<T>(this string input, Func<string, T> action, T defaultvalue) where T : struct
        {
            if (string.IsNullOrEmpty(input))
            {
                return defaultvalue;
            }
            try
            {
                return action(input);
            }
            catch
            {
                return defaultvalue;
            }
        }

  這段代碼的核心部分就是通過傳入一個Func<string, T>類型的委托去構建代碼和算法的重用,這里涉及到一些重要的思想,一個是代碼重用思想,另外就是體會到使用泛型參數T來真正地實現算法的重用機制,另外通過這個我們也可以橫向比較Action、Func類型的委托以及匿名委托delegate的一些區別。

 public static class ParseUtil
    {
        public static DateTime ParseByDefault(this string input, DateTime defaultvalue)
        {
            return input.ParseStringToType<DateTime>(delegate(string e)
            {
                return Convert.ToDateTime(input);
            }, defaultvalue);
        }

        public static decimal ParseByDefault(this string input, decimal defaultvalue)
        {
            return input.ParseStringToType<decimal>(delegate(string e)
            {
                return Convert.ToDecimal(input);
            }, defaultvalue);
        }

        public static double ParseByDefault(this string input, double defaultvalue)
        {
            return input.ParseStringToType<double>(delegate(string e)
            {
                return Convert.ToDouble(input);
            }, defaultvalue);
        }

        public static int ParseByDefault(this string input, int defaultvalue)
        {
            return input.ParseStringToType<int>(delegate(string e)
            {
                return Convert.ToInt32(input);
            }, defaultvalue);
        }

        public static long ParseByDefault(this string input, long defaultvalue)
        {
            return input.ParseStringToType<long>(delegate(string e)
            {
                return Convert.ToInt64(input);
            }, defaultvalue);
        }

        public static float ParseByDefault(this string input, float defaultvalue)
        {
            return input.ParseStringToType<float>(delegate(string e)
            {
                return Convert.ToSingle(input);
            }, defaultvalue);
        }

        public static float ParseByDefault(this string input, short defaultvalue)
        {
            return input.ParseStringToType<short>(delegate(string e)
            {
                return Convert.ToInt16(input);
            }, defaultvalue);
        }

        public static string ParseByDefault(this string input, string defaultvalue)
        {
            if (string.IsNullOrEmpty(input))
            {
                return defaultvalue;
            }
            return input;
        }

        private static T ParseStringToType<T>(this string input, Func<string, T> action, T defaultvalue) where T : struct
        {
            if (string.IsNullOrEmpty(input))
            {
                return defaultvalue;
            }
            try
            {
                return action(input);
            }
            catch
            {
                return defaultvalue;
            }
        }
    }

  另外在傳入參數input之前為什么還需要傳遞this?這個該如何去准確理解呢?

  這就涉及到C# this擴展方法的內容了......

  擴展方法被定義為靜態方法,但它們是通過實例方法語法進行調用的。 它們的第一個參數指定該方法作用於哪個類型,並且該參數以 this 修飾符為前綴。 擴展方法當然不能破壞面向對象封裝的概念,所以只能是訪問所擴展類的public成員。     

  擴展方法使您能夠向現有類型“添加”方法,而無需創建新的派生類型、重新編譯或以其他方式修改原始類型。擴展方法是一種特殊的靜態方法,但可以像擴展類型上的實例方法一樣進行調用,C#擴展方法第一個參數指定該方法作用於哪個類型,並且該參數以 this 修飾符為前綴。

  就像上面的方法中,input是一個string類型的對象,但是 ParseStringToType這個方法是我們自己定義的一個靜態方法,String類中是不存在該方法的,是我們人為去擴展的一個方法,下面舉出一個相同的例子:  

	//必須是靜態類才可以添加擴展方法
       Static class Program
       {
          static void Main(string[] args)
          {
            string str = "quzijing";
            //注意調用擴展方法,必須用對象來調用 
            string Newstr = str.Add();
            Console.WriteLine(Newstr);
            Console.ReadKey();
          }
        //聲明擴展方法
        //擴展方法必須是靜態的,Add有三個參數
        //this 必須有,string表示我要擴展的類型,stringName表示對象名
        //三個參數this和擴展的類型必不可少,對象名可以自己隨意取如果需要傳遞參數,//再增加一個變量即可

          public static  string  Add(this string stringName)
          {
            return stringName+"a";
          }
      }		

  既然string類可以通過這種方式來擴展方法,那么我們定義的一般類呢?答案也是可以的。  

  給自定義的類型增加一個擴展方法,並增加一個傳遞的參數

  (1)、聲明一個Student類,它包含了兩個方法StuInfo,getStuInfo

 public class Student
    {
        public string StuInfo()
        {
            return "學生基本信息";
        }
        public  string getStuInfo(string stuName, string stuNum)
        {
       return string.Format("學生信息:\\n" + "姓名:{0} \\n" + "學號:{1}",      stuName, stuNum);
        }
     } 

  (2)、聲明一個名為ExtensionStudentInfo的靜態類,注意必須為靜態

  這個類的作用就是包含一些我們想要擴展的方法,在此我們聲明兩個Student類型的擴展方法,Student類型為我們自定義的類型。

public static class ExtensionStudentInfo
    {
        //聲明擴展方法
        //要擴展的方法必須是靜態的方法,Add有三個參數
        //this 必須有,string表示我要擴展的類型,stringName表示對象名
        //三個參數this和擴展的類型必不可少,對象名可以自己隨意取如果需要傳遞參數,再增加一個變量即可
        public static string ExtensionStuInfo(this Student stuName)
        {
            return stuName.StuInfo();
        }
        //聲明擴展方法
        //要擴展的方法必須是靜態的方法,Add有三個參數
        //this 必須有,string表示我要擴展的類型,stringName表示對象名
        //三個參數this和擴展的類型必不可少,對象名可以自己隨意取如果需要傳遞參數,在此我們增加了兩個string類型的參數
        public static string ExtensionGetStuInfo(this Student student, string stuname, string stunum)
        {
            return student.getStuInfo(stuname, stunum)+"\\n讀取完畢";
        }
    }

    下面來建一個測試的應用程序來看看輸出的結果

 static void Main(string[] args)
        {
            Student newstudent = new Student();
            //要使用對象調用我們的擴展方法
            string stuinfo = newstudent.ExtensionStuInfo();
            Console.WriteLine(stuinfo);
            //要使用對象調用我們的擴展方法
            string stuinformation = newstudent.ExtensionGetStuInfo("張三", "001");
            Console.WriteLine(stuinformation);
            Console.ReadKey();
        }

  獲取的結果是:

最后借用網上的一個例子來結束這一內容的介紹。
		
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions; 
//聲明擴展方法的步驟:類必須是static,方法是static,
//第一個參數是被擴展的對象,前面標注this。
//使用擴展方法的時候必須保證擴展方法類已經在當前代碼中using
namespace 擴展方法
{

    //擴展方法必須是靜態的
    public static class StringHelper
    {
        //擴展方法必須是靜態的,第一個參數必須加上this
        public static bool IsEmail(this string _input)
        {
            return Regex.IsMatch(_input, @"^\\w+@\\w+\\.\\w+$");
        }

        //帶多個參數的擴展方法
        //在原始字符串前后加上指定的字符
        public static string Quot(this string _input, string _quot)
        {
            return _quot + _input + _quot;
        }

    }

}	

  通過擴展類,我們可以為string類擴展一些原先不太需要的方法來完成我們的需求。

			
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 擴展方法
{
    class Program
    {
        static void Main(string[] args)
        {
            string _myEmail = "abc@163.com";
            //這里就可以直接使用string類的擴展方法IsEmail了
            Console.WriteLine(_myEmail.IsEmail());
            //調用接收參數的擴展方法
            Console.WriteLine(_myEmail.Quot("!"));
            Console.ReadLine();
        }

    }

}		

  就像我們的ParseUtil類定義的那樣,我們可以通過定義string str,然后通過str.ParseByDefault(0D)直接將我們將string直接轉化為double類型,而不用在每個地方都重復去寫代碼,這些都需要我們不斷去反思總結代碼,代碼才能越寫越好;

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM