C#中的ICustomFormatter及IFormatProvider接口用法揭秘
最近在學(xué)習(xí)IFormatProvider接口的用法時(shí),在網(wǎng)絡(luò)上找了段實(shí)例代碼(具體哪個(gè)網(wǎng)站不記得了,就不給出鏈接了),通過研究實(shí)例代碼,初步了解了IFormatProvider接口的用法。
在學(xué)習(xí)代碼之前,我們先來了解一下本例中使用到的兩個(gè)接口ICustomFormatter及IFormatProvider。
查看MSDN,得到以下關(guān)于ICustomFormatter及IFormatProvider接口的說明。
接口ICustomFormatter:定義一種方法,它支持自定義設(shè)置對象的值的格式。 ICustomFormatter 接口包含單個(gè)方法:ICustomFormatter.Format。當(dāng)此接口由引用或值類型實(shí)現(xiàn)時(shí),F(xiàn)ormat 方法會返回對象值的自定義格式字符串表示形式。
接口IFormatProvider:提供用于檢索控制格式化的對象的機(jī)制。 類或數(shù)值類型實(shí)現(xiàn)此接口的 GetFormat方法,以獲得提供格式信息或?qū)崿F(xiàn)類型的處理的對象。IFormatProvider接口同樣只包含一個(gè)方法。
可能單純閱讀MSDN的說明,還是有點(diǎn)一知半解的感覺。
不過,別急,繼續(xù)往下看。
下面給出詳細(xì)代碼,看下面...
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(暫且叫作“自定義格式化類”),該類實(shí)現(xiàn)了ICustomFormatter及IFormatProvider接口,所以該類實(shí)現(xiàn)了 GetFormat及Format方法,其實(shí)該類除了實(shí)現(xiàn)這兩個(gè)方法外,也沒有完成其他任何工作。
GetFormat方法對傳入?yún)?shù)(類型format)進(jìn)行判斷,如果傳入的類型format為ICustomFormatter,就返回類本身,否則返回null。我個(gè)人的理解就是:調(diào)用MyFormater類的GetFormat方法時(shí),傳入類型要求,告訴類MyFormater,你必須滿足類型要求,否則我就不要你了,你要是滿足條件,我就要定你了。從MyFormater的角度來思考的話,就是:我(MyFormater)就能提供類型為ICustomFormatter的我。舉個(gè)不恰當(dāng)?shù)睦樱惴堑靡獋€(gè)人妖,我怎么能給你呢,我可是絕對的純爺們,呵呵大哭??梢?,GetFormat方法主要提供一個(gè)滿足指定要求的對象,該對象提供格式信息。那該對象提供的格式信息由誰來提供呢,當(dāng)然是Format方法,msdn對這個(gè)有很明確的說明,“Format 方法會返回對象值的自定義格式字符串表示形式。”
學(xué)習(xí)到這里,是不是感覺自己有一丁點(diǎn)的明白了呢。
如果還是一團(tuán)漿糊,也沒事,接著往下看。
不過,到這里,不管你腦子里到底有多漿糊。我都希望你至少能明白一點(diǎn),那就是GetFormat方法負(fù)責(zé)返回提供格式信息的對象(這里的MyFormater),而Format 方法負(fù)責(zé)返回具體的格式信息。說得再簡單點(diǎn),那就是:先得到提供格式化信息的對象,再得到該對象提供的格式化信息。
好了,不羅嗦了,繼續(xù)往下看。
在解釋Format方法的具體實(shí)現(xiàn)前,先來看看我們的代碼到底是怎樣運(yùn)行的。
在Main函數(shù)中,定義整型變量i,并初始化為100;定義字符串printString用來保存返回值;實(shí)例化MyFormater,得到對象myFormater。并調(diào)用string.Format方法生成printString。
printString = string.Format(myFormater, "{0}", i); printString = string.Format(myFormater, "{0:C}", i); printString = string.Format(myFormater, "{0:MyFormater}", i);
代碼中采用上面三種方式來調(diào)用string.Format方法,三者的區(qū)別僅在第二個(gè)參數(shù)。要想弄清楚三者的區(qū)別,只有搞清楚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); }
結(jié)合我們的函數(shù)調(diào)用閱讀函數(shù)簽名,了解到:string.Format方法的第一個(gè)參數(shù)接收我們傳入的自定義格式化類對象myFormater,第二個(gè)參數(shù)接收格式化字符串format,第三個(gè)參數(shù)接收需要被格式化的參數(shù)集合args,這里僅變量i。
查看string.Format方法體,可以了解到:方法先對傳入?yún)?shù)format及args進(jìn)行非法判斷,參數(shù)為空時(shí)拋出參數(shù)空異常。參數(shù)正常時(shí),初始化StringBuilder 對象(關(guān)于StringBuilderCache.Acquire的使用這里不做過多介紹,自己去研究),接著調(diào)用sb.AppendFormat方法,最后通過語句return StringBuilderCache.GetStringAndRelease(sb)返回結(jié)果??梢姡嬲母袷交僮鞫荚趕b.AppendFormat方法中完成,這里并不打算給出sb.AppendFormat方法的完整代碼,只是給出sb.AppendFormat方法中調(diào)用GetFormat 方法和Format 方法的代碼。
if (provider != null) { formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter)); }
代碼傳入?yún)?shù)typeof(ICustomFormatter),返回ICustomFormatter類型的formatter 。
if (formatter != null) { if (builder != null) { str = builder.ToString(); } str2 = formatter.Format(str, arg, provider); }
上面就是代碼中調(diào)用Format方法的地方。
執(zhí)行上面代碼都會去執(zhí)行我們的自定義格式化類MyFormater的代碼。
要想了解詳細(xì)的執(zhí)行情況,那就請代開你的VS,開始敲代碼吧。
好像到這里,我也沒有把問題很好的解釋清楚。
這與我對.NET庫代碼一竅不通是有很大關(guān)系的。其實(shí),到這里,我對sb.AppendFormat方法的具體操作也還是停留在了解的層面上,所以就沒有過多敘述了。希望大家能諒解。但是到最后,大家至少對我們自定義的格式化類MyFormater在.NET庫中是如何被使用的應(yīng)該有一個(gè)初步認(rèn)識了。
就到這里了。最后給出程序執(zhí)行結(jié)果??聪旅?..
哦,忘了解釋Format方法的代碼,哎,太累了,就不解釋了,大家都是牛人,能看懂的。
相關(guān)文章
IIS下調(diào)用證書出現(xiàn)異常的解決方法 (C#)
這篇文章主要為大家詳細(xì)介紹了IIS下調(diào)用證書出現(xiàn)異常的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別
C#靜態(tài)方法與非靜態(tài)方法的區(qū)別不僅僅是概念上的,那么他們有什么具體的區(qū)別呢?讓我們通過本文向大家介紹下C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別,一起看看吧2017-09-09C# 實(shí)現(xiàn)視頻監(jiān)控系統(tǒng)(附源碼)
這篇文章主要介紹了C# 如何實(shí)現(xiàn)視頻監(jiān)控系統(tǒng),幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02