用泛型来实现编译时期的类型推断
兩個方法,一個讀取Xml生成Object的實例,另一個把一個obj保存成一個Xml。這里有幾個缺點
①每次調用LoadFromFile方法,必須有一個類型轉換,從Object轉成自己要的類型,寫的時候肯定不會報錯的,因為Object是所有類型的基類,但是運行的時候,就不一定了~~ 。
②這是一個性能問題。每次調用這兩個方法的時候,都重新new 了一個XmlSerializer對象。Framework的設計者是會盡量降低new對象的代價,但畢竟是需要創(chuàng)建,然后銷毀一些零時的變量。
看到第二點,大家都會想到把XmlSerializer類型對象factory作為一個XmlPersistenceManager的靜態(tài)成員變量。
看到第二點可能會寫出下面的代碼。
1: public static class XmlPersistenceManager2 2: { 3: private static XmlSerializer factory; 4: public static object LoadFromFile(Type typeToLoad, string filePath) 5: { 6: if (factory == null) 7: factory = new XmlSerializer(typeToLoad); 8:? 9: if (File.Exists(filePath)) { 10: using (TextReader tr = new StreamReader(filePath)) { 11: object rVal = factory.Deserialize(tr); 12: return rVal; 13: } 14: } 15: return default(object);//null 16: } 17: public static void SaveToFile(string filePath, object obj) 18: { 19: Type theType = obj.GetType(); 20: if (factory == null) factory = new XmlSerializer(theType); 21: using (var sw = new StreamWriter(filePath, false)) { 22: factory.Serialize(sw, obj); 23: } 24: } 25: }性能問題是解決了,但是,明顯,有個bug。20行,先ClassA類型的obj調用,factory生成一個實例,木有問題;然后來一個ClassB類型的obj調用,factory != null ;然后,22行,調用,異常就來了。 原先我以為是不會出錯的,充其量應該只是生成一個空的xml文件,但原文用了Exception這個詞,然后自己測試了一下。證明,我錯了,確實是Exception,再看一下代碼,factory實例化的時候傳入了參數(shù)theType。為什么要傳這個參數(shù)呢?我想應該還是性能問題吧。new 一個 XmlSerializer 之后肯定不會只(反)序列化同類型的對象一次。
要解決這個bug也很容易,用一個Dictionary來存XmlSerializer對象。。。但是這樣意味著要寫更多代碼,寫更多編譯器和JIT引擎可以幫你實現(xiàn)的代碼。
接下來泛型上場,原文叫“correct answer”。
1: public static class GenericXmlPersistenceManager<T> 2: { 3: private static XmlSerializer factory; 4: public static T LoadFromFile(string filePath) 5: { 6: if (File.Exists(filePath)) { 7: using (XmlReader inputStream = XmlReader.Create(filePath)) { 8: if (factory == null) factory = new XmlSerializer(typeof(T)); 9: T rVal = (T)factory.Deserialize(inputStream); 10: return rVal; 11: } 12: } 13: return default(T); 14: } 15: public static void SaveToFile(string filePath, T data) 16: { 17: using (XmlWriter writer = XmlWriter.Create(filePath)) { 18: if (factory == null) factory = new XmlSerializer(typeof(T)); 19: factory.Serialize(writer, data); 20: } 21: } 22: }代碼上和最初的版本沒有什么太大差異。解決了原先的幾個問題。
①類型轉換。泛型類中的LoadFromFile方法,返回的類型其實已經(jīng)被限定了,就是T類型,至于T具體是什么類型,就看自己在調用的時候尖括號之間寫的具體的值了。
②性能問題和那個Exception bug。用了靜態(tài)變量,緩存了XmlSerializer對象,當序列化同個類型的obj的時候,不需再去重新new一個XmlSerializer。并且,如果傳入了不同類型的obj,也會重新new一個對應類型的XmlSerializer 類型的factory,這樣就不會報錯。(想到一個問題,寫完之后查資料了解一下)。
?
最后一段:
很多時候如果用了Type類型的參數(shù),通常都可以定義出一個泛型的版本。編譯器就會 “Create the Specific version for you.”。
轉載于:https://www.cnblogs.com/sheldon-lou/p/3443734.html
總結
以上是生活随笔為你收集整理的用泛型来实现编译时期的类型推断的全部內容,希望文章能夠幫你解決所遇到的問題。