怎樣深度拷貝最快呢?
假設有這樣的倆個物件
public class people
public string name
public string ***
}
public class man
public int age
public string name
public string ***
}
如果我們將people的所有屬性都賦值給man。如果數量不多,我們乙個個手寫就好了,但是假設物件屬性有成百上千個怎麼辦???乙個個手寫?那還不累死!
一般情況下有倆種辦法
第一種,反射,逐個複製,但是我們都知道,反射是很慢的。效能並不好;
第二種,通過jsonconverter.序列化再反序列化,(⊙o⊙)…。效能比反射還差。
那有什麼更好的辦法嗎???
第一種 通過位元組緩衝。將成員資訊緩衝到字典裡面去,讀取的時候再去裡面查詢。但是我們知道,字典是比較耗費時間的。
第二種 泛型緩衝,啥叫泛型緩衝?其實在c#裡面 例如類 list在編譯之後和 list還有關係嗎? 其實編譯器是將其編譯成為了倆單獨的類。如果我們將我們的資料 存在類裡面那麼效能便是最高最快的。
廢話說多了,貼**。
_";if (!keyvaluepairs.containskey(key))
return ((func)keyvaluepairs[key]).invoke(tin);
}/// /// 複製資訊
///
///
/// 物件成員列表
/// 成員繫結表
/// 表示式引數
private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)
var gg = propertys.getproperty(item.name);
if (gg == null)
var property = expression.property(parameter, gg);
var member = expression.bind(item, property);
memberbindings.add(member);}}
}上面的**是幹啥的?核心就是動態生成linq語句。逐個將屬性讀取出來,然後逐個編寫linq 屬性賦值語句,最後新建初始化tout。
我們知道 在字典裡查詢資料時其實是通過傳入key的雜湊值查詢的,速度還是比較慢的。我們再次優化
private static funcfunc = null;
/// /// 深度複製
///
///
///
public static tout copy(tin tin) => func.invoke(tin);
/// /// 複製資訊
///
///
/// 物件成員列表
/// 成員繫結表
/// 表示式引數
private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)
var gg = propertys.getproperty(item.name);
if (gg == null)
var property = expression.property(parameter, gg);
var member = expression.bind(item, property);
memberbindings.add(member);}}
}公升級後一對tin和tout對應乙個新的類。如此相當於我們直接操作類了,效能槓槓的。
呼叫就簡單了。非常簡單。如下
var peop = new people() ;
第一次呼叫泛型緩衝時,我們會呼叫其靜態構造器,並生成其靜態賦值委託。第二次呼叫時由於 靜態構造器只呼叫一次,我們就直接呼叫其泛型委託了,啊哈,一下就賦值完成。
經過100萬次賦值測試,泛型委託深拷貝方式 是 原生硬編碼的倆倍。快不快?字典形式深拷貝是原生硬碼方式的10倍。反射和序列化方式是原生硬編碼的100多倍。
最後我們將上面的**優化掉,乙個擴充套件方法使用起來可就美滋滋了
/// /// 轉殖擴充套件///
public static class cloneextension
_";if (!keyvaluepairs.containskey(key))
return ((func)keyvaluepairs[key]).invoke(tin);
}/// /// 複製資訊
///
///
/// 物件成員列表
/// 成員繫結表
/// 表示式引數
private static void copy(ienumerablememberinfos, listmemberbindings, parameterexpression parameter)
var gg = propertys.getproperty(item.name);
if (gg == null)
var property = expression.property(parameter, gg);
var member = expression.bind(item, property);
memberbindings.add(member);}}
}
C 預設拷貝建構函式 深度拷貝和淺拷貝
c 類的中有兩個特殊的建構函式,1 無參建構函式,2 拷貝建構函式。它們的特殊之處在於 1 當類中沒有定義任何建構函式時,編譯器會預設提供乙個無參建構函式且其函式體為空 2 當類中沒有定義拷貝建構函式時,編譯器會預設提供乙個拷貝建構函式,進行成員變數之間的拷貝。這個拷貝操作是淺拷貝 這裡只講拷貝建構...
深度拷貝和潛拷貝
淺 復 制 在複製操作時,對於被複製的物件的每一層複製都是指標複製。深 復 制 在複製操作時,對於被複製的物件至少有一層複製是物件複製。完全複製 在複製操作時,對於被複製的物件的每一層複製都是物件複製。注 1 在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。2 對於...
C deep copy 深度拷貝
當類的成員變數存在指標型別時,如果採用賦值語句將乙個該類物件賦給另外乙個物件時,缺省會採用淺拷貝,也即兩個指標型別的成員變數指向同乙個位址,這樣當物件生命週期結束時會呼叫析構函式,釋放相應的記憶體位址。但是由於淺拷貝,會導致釋放發生兩次,如此第二次釋放發生時,因為已經被釋放過一次,所以程式會奔潰。如...