// when we can't use code generation, we can use these methods internal static T[] Clone1DimArraySafeInternal <T>(T[] obj, DeepCloneState state) { var l = obj.Length; var outArray = new T[l]; state.AddKnownRef(obj, outArray); Array.Copy(obj, outArray, obj.Length); return(outArray); }
internal static T[] Clone1DimArrayClassInternal <T>(T[] obj, DeepCloneState state) { // not null from called method, but will check it anyway if (obj == null) { return(null); } var l = obj.Length; var outArray = new T[l]; state.AddKnownRef(obj, outArray); for (var i = 0; i < l; i++) { outArray[i] = (T)CloneClassInternal(obj[i], state); } return(outArray); }
// relatively frequent case. specially handled internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state) { // not null from called method, but will check it anyway if (obj == null) { return(null); } var l1 = obj.GetLength(0); var l2 = obj.GetLength(1); var outArray = new T[l1, l2]; state.AddKnownRef(obj, outArray); if (DeepClonerSafeTypes.CanReturnSameObject(typeof(T))) { Array.Copy(obj, outArray, obj.Length); return(outArray); } if (typeof(T).GetTypeInfo().IsValueType) { var cloner = GetClonerForValueType <T>(); for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { outArray[i, k] = cloner(obj[i, k], state); } } } else { for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { outArray[i, k] = (T)CloneClassInternal(obj[i, k], state); } } } return(outArray); }
internal static T[] Clone1DimArrayStructInternal <T>(T[] obj, DeepCloneState state) { // not null from called method, but will check it anyway if (obj == null) { return(null); } var l = obj.Length; var outArray = new T[l]; state.AddKnownRef(obj, outArray); var cloner = GetClonerForValueType <T>(); for (var i = 0; i < l; i++) { outArray[i] = cloner(obj[i], state); } return(outArray); }
// rare cases, very slow cloning. currently it's ok internal static Array CloneAbstractArrayInternal(Array obj, DeepCloneState state) { // not null from called method, but will check it anyway if (obj == null) { return(null); } var rank = obj.Rank; var lowerBounds = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray(); var lengths = Enumerable.Range(0, rank).Select(obj.GetLength).ToArray(); var idxes = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray(); var outArray = Array.CreateInstance(obj.GetType().GetElementType(), lengths, lowerBounds); state.AddKnownRef(obj, outArray); while (true) { outArray.SetValue(CloneClassInternal(obj.GetValue(idxes), state), idxes); var ofs = rank - 1; while (true) { idxes[ofs]++; if (idxes[ofs] >= lowerBounds[ofs] + lengths[ofs]) { idxes[ofs] = lowerBounds[ofs]; ofs--; if (ofs < 0) { return(outArray); } } else { break; } } } }