泛函/泛型 指的是編譯時不需要指定具體的參數類型,可以在運行時動態地賦予某一種數據類型的機制。 相信很多人對泛型並不陌生,像Dictionary,List等結構都屬於泛型。有趣的是,一個函數也可以泛化。
假如我們需要些一個函數,這個函數負責某一種邏輯操作(例如排序、求和、個數統計等),而不關心具體要操作的數據類型是什麼,那麼為了使這個函數變得更通用,就可以寫成泛函。
舉一個我遇到的簡單例子:
項目中經常要寫讀文件,生成key-value 結構的字典。 每次都寫StreamReader 和 Dicitonary 的句子會讓人感覺碼農真是一份無聊的職業。於是寫了一個通用的加載key-value 字典的泛函:
class Common { internal static Dictionary<T1, T2> LoadDict<T1, T2>(string file, char sep, bool hasHeader = false, int keyidx=0, int valueidx=1) { Dictionary<T1, T2> res = new Dictionary<T1, T2>(); using (StreamReader rd = new StreamReader(file)) { string content = ""; if (hasHeader) rd.ReadLine(); while ((content = rd.ReadLine()) != null) { string[] words = content.Split(sep); T1 key = (T1) Convert.ChangeType(words[keyidx], typeof(T1)); T2 value = (T2)Convert.ChangeType(words[valueidx], typeof(T2)); if (!res.ContainsKey(key)) res.Add(key, value); } } return res; } }
這樣只要調用Common.LoadDict<string,int>( filename, ...) 就可以了。這個函數就像是一個模板,在運行時再確定要使用什麼樣的數據類型。
T1 key = (T1) Convert.ChangeType(words[keyidx], typeof(T1));
如果類型操作還有更細致的要求,那麼可以這樣:
if (typeof(T) == typeof(int)) { ... } else if (typeof(T) == typeof(double)) { ... } else ...