最近在學習IFormatProvider接口的用法時,在網絡上找了段實例代碼(具體哪個網站不記得了,就不給出鏈接了),通過研究實例代碼,初步了解了IFormatProvider接口的用法。
在學習代碼之前,我們先來了解一下本例中使用到的兩個接口ICustomFormatter及IFormatProvider。
查看MSDN,得到以下關于ICustomFormatter及IFormatProvider接口的說明。
接口ICustomFormatter:定義一種方法,它支持自定義設置對象的值的格式。 ICustomFormatter 接口包含單個方法:ICustomFormatter.Format。當此接口由引用或值類型實現時,Format 方法會返回對象值的自定義格式字符串表示形式。
接口IFormatProvider:提供用于檢索控制格式化的對象的機制。 類或數值類型實現此接口的 GetFormat方法,以獲得提供格式信息或實現類型的處理的對象。IFormatProvider接口同樣只包含一個方法。
可能單純閱讀MSDN的說明,還是有點一知半解的感覺。
不過,別急,繼續往下看。
下面給出詳細代碼,看下面...
public class MyFormater:ICustomFormatter,IFormatProvider{  public object GetFormat(Type format)  {    if (format == typeof(ICustomFormatter))      return this;    return null;  }  public string Format(string format, object arg, IFormatProvider provider)  {    if (format == null)    {      if (arg is IFormattable)       return ((IFormattable)arg).ToString(format, provider);      return arg.ToString();    }    else    {      if (format == "MyFormater")      {        return "**" + arg.ToString();      }      else      {        if (arg is IFormattable)          return ((IFormattable)arg).ToString(format, provider);        return arg.ToString();      }    }  }}static void Main(string[] args){      int i = 100;   string printString;   MyFormater myFormater = new MyFormater();   printString = string.Format(myFormater, "{0}", i);   Console.WriteLine("{0}", printString);   printString = string.Format(myFormater, "{0:C}", i);   Console.WriteLine("{0}", printString);   printString = string.Format(myFormater, "{0:MyFormater}", i);   Console.WriteLine("{0}", printString);}代碼中定義了類MyFormater(暫且叫作“自定義格式化類”),該類實現了ICustomFormatter及IFormatProvider接口,所以該類實現了 GetFormat及Format方法,其實該類除了實現這兩個方法外,也沒有完成其他任何工作。
GetFormat方法對傳入參數(類型format)進行判斷,如果傳入的類型format為ICustomFormatter,就返回類本身,否則返回null。我個人的理解就是:調用MyFormater類的GetFormat方法時,傳入類型要求,告訴類MyFormater,你必須滿足類型要求,否則我就不要你了,你要是滿足條件,我就要定你了。從MyFormater的角度來思考的話,就是:我(MyFormater)就能提供類型為ICustomFormatter的我。舉個不恰當的例子,你非得要個人妖,我怎么能給你呢,我可是絕對的純爺們,呵呵大哭。可見,GetFormat方法主要提供一個滿足指定要求的對象,該對象提供格式信息。那該對象提供的格式信息由誰來提供呢,當然是Format方法,msdn對這個有很明確的說明,“Format 方法會返回對象值的自定義格式字符串表示形式。”
學習到這里,是不是感覺自己有一丁點的明白了呢。
如果還是一團漿糊,也沒事,接著往下看。
不過,到這里,不管你腦子里到底有多漿糊。我都希望你至少能明白一點,那就是GetFormat方法負責返回提供格式信息的對象(這里的MyFormater),而Format 方法負責返回具體的格式信息。說得再簡單點,那就是:先得到提供格式化信息的對象,再得到該對象提供的格式化信息。
好了,不羅嗦了,繼續往下看。
在解釋Format方法的具體實現前,先來看看我們的代碼到底是怎樣運行的。
在Main函數中,定義整型變量i,并初始化為100;定義字符串printString用來保存返回值;實例化MyFormater,得到對象myFormater。并調用string.Format方法生成printString。
printString = string.Format(myFormater, "{0}", i);printString = string.Format(myFormater, "{0:C}", i);printString = string.Format(myFormater, "{0:MyFormater}", i);代碼中采用上面三種方式來調用string.Format方法,三者的區別僅在第二個參數。要想弄清楚三者的區別,只有搞清楚string.Format方法到底做了些什么才能知道,所以下面來看看string.Format方法都做了些什么。
在這里,我們需要使用Reflector來查看string.Format方法的源碼。
string.Format方法的代碼如下:
public static string Format(IFormatProvider provider, string format, params object[] args){  if ((format == null) || (args == null))  {    throw new ArgumentNullException((format == null) ? "format" : "args");  }  StringBuilder sb = StringBuilderCache.Acquire(format.Length + (args.Length * 8));  sb.AppendFormat(provider, format, args);  return StringBuilderCache.GetStringAndRelease(sb);}結合我們的函數調用閱讀函數簽名,了解到:string.Format方法的第一個參數接收我們傳入的自定義格式化類對象myFormater,第二個參數接收格式化字符串format,第三個參數接收需要被格式化的參數集合args,這里僅變量i。
查看string.Format方法體,可以了解到:方法先對傳入參數format及args進行非法判斷,參數為空時拋出參數空異常。參數正常時,初始化StringBuilder 對象(關于StringBuilderCache.Acquire的使用這里不做過多介紹,自己去研究),接著調用sb.AppendFormat方法,最后通過語句return StringBuilderCache.GetStringAndRelease(sb)返回結果。可見,真正的格式化操作都在sb.AppendFormat方法中完成,這里并不打算給出sb.AppendFormat方法的完整代碼,只是給出sb.AppendFormat方法中調用GetFormat 方法和Format 方法的代碼。
if (provider != null){    formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter)); }代碼傳入參數typeof(ICustomFormatter),返回ICustomFormatter類型的formatter 。
if (formatter != null){  if (builder != null)  {    str = builder.ToString();      }  str2 = formatter.Format(str, arg, provider);}上面就是代碼中調用Format方法的地方。
執行上面代碼都會去執行我們的自定義格式化類MyFormater的代碼。
要想了解詳細的執行情況,那就請代開你的VS,開始敲代碼吧。
好像到這里,我也沒有把問題很好的解釋清楚。
這與我對.NET庫代碼一竅不通是有很大關系的。其實,到這里,我對sb.AppendFormat方法的具體操作也還是停留在了解的層面上,所以就沒有過多敘述了。希望大家能諒解。但是到最后,大家至少對我們自定義的格式化類MyFormater在.NET庫中是如何被使用的應該有一個初步認識了。
就到這里了。最后給出程序執行結果。看下面...

哦,忘了解釋Format方法的代碼,哎,太累了,就不解釋了,大家都是牛人,能看懂的。
新聞熱點
疑難解答