C# List引用型別的克隆
有時候我們想克隆一個List去做別的事,而不影響原來的List,我們直接在list後面加上小點點,發現並沒有Clone這樣的擴充套件函式。這時候就只有自己擴充套件了。
嘗試了三種方式,測試都通過了,至於效能方面我還沒有做測試。
一、反射
1public static List<T> Clone<T>(this List<T> list) where T : new() 2{ 3List<T> items = new List<T>(); 4foreach (var m in list) 5{ 6var model = new T(); 7var ps = model.GetType().GetProperties(); 8var properties = m.GetType().GetProperties(); 9foreach (var p in properties) 10{ 11foreach (var pm in ps) 12{ 13if (pm.Name == p.Name) 14{ 15pm.SetValue(model, p.GetValue(m)); 16} 17} 18} 19items.Add(model); 20} 21return items; 22}
二、序列化(依賴Newtonsoft.Json)
1public static List<T> Clone<T>(this List<T> list) where T : new() 2{ 3var str = JsonConvert.SerializeObject(list); 4return JsonConvert.DeserializeObject<List<T>>(str); 5}
三、序列化(BinaryFormatter)
1 public static List<T> Clone<T>(this List<T> list) 2{ 3using (Stream objectStream = new MemoryStream()) 4{ 5IFormatter formatter = new BinaryFormatter(); 6formatter.Serialize(objectStream, list); 7objectStream.Seek(0, SeekOrigin.Begin); 8return (List<T>)formatter.Deserialize(objectStream); 9} 10}
測試
1 private void Test() 2 { 3List<NormalSetting> list = new List<NormalSetting>(); 4list.Add(new NormalSetting { RedisIp = "123" }); 5List<NormalSetting> items = list.Clone(); 6list[0].RedisIp = "456"; 7logMessager.Show("{0}:{1}", list[0].RedisIp, items[0].RedisIp); 8 }
注意事項:
第一種方式無需任何依賴。
第二種方式需要Newtonsoft.Json,如果專案中沒有用到它,不推薦使用這種方式。
第三種方式序要給引用型別實體加上[Serializable]特性