Try to create a deep clone of an Array or a standard clone of a scalar. - CSharp System

CSharp examples for System:Array Create

Description

Try to create a deep clone of an Array or a standard clone of a scalar.

Demo Code

/*//from   ww  w.j a v  a2s.c  om
    * Copyright: Thomas McGlynn 1997-2007.
    * 
    * The CSharpFITS package is a C# port of Tom McGlynn's
    * nom.tam.fits Java package, initially ported by  Samuel Carliles
    *
    * Copyright: 2007 Virtual Observatory - India.     
    *
    * Use is subject to license terms
    */
using System.Collections;
using System;

public class Main{
        /// <summary>Try to create a deep clone of an Array or a standard clone of a scalar.
        /// The object may comprise arrays of any primitive type or any Object type which
        /// implements Cloneable.  However, if the Object is some kind of collection,
        /// e.g., a Vector then only a shallow copy of that object is made.  I.e., deep
        /// refers only to arrays.
        /// </summary>
        /// <param name="o">The object to be copied.</param>
        /*TODO: If multidimension array is passed as an input, it is getting flattened out
        TODO: For normal multidimension, we get an error because NewInstance always returns Jagged array.*/
        public static System.Object DeepClone(System.Object o)
        {
            if (o == null)
            {
                return null;
            }
            if (!o.GetType().IsArray)
            {
                return GenericClone(o);
            }

            Array a = (Array)o;
            if (ArrayFuncs.IsArrayOfArrays(o))
            {
                Array result = NewInstance(o.GetType().GetElementType(), a.Length);
                for (int i = 0; i < result.Length; ++i)
                {
                    result.SetValue(DeepClone(a.GetValue(i)), i);
                }

                return result;
            }
            else
            {
                int[] lengths = new int[a.Rank];
                for (int i = 0; i < lengths.Length; ++i)
                {
                    lengths[i] = a.GetLength(i);
                }
                Array result = ArrayFuncs.NewInstance(o.GetType().GetElementType(), lengths);
                Array.Copy(a, result, a.Length);

                return result;
            }
            return null;
        }
        /// <summary>
        /// Checks whether the object is a type of Array of Arrays
        /// </summary>
        /// <param name="o"></param>
        /// <returns>Returns boolean depending upon the Arra type</returns>
        public static bool IsArrayOfArrays(Object o)
        {
            if (o == null || !o.GetType().IsArray)
            {
                return false;
            }

            // If the object passed is of type Multi-dimension Array
            if (((Array)o).Rank > 1)
            {
                IEnumerator e = ((Array)o).GetEnumerator();

                int i = 0;

                // If the argument passed is a multi-dimension array,
                // like int[2,2], below loop will give you back 'false';
                // If the input is Array[2,2]. below loop would return 'true'
                // as each element is an array.
                for (; e.MoveNext(); i++)
                {
                    if (e.Current != null && e.Current.GetType().IsArray)
                    {
                        return true;
                    }
                    else if (e.Current != null && !e.Current.GetType().IsArray)
                    {
                        return false;
                    }
                    else if (e.Current == null)
                    {
                        continue;
                    }
                }
                if (i == ((Array)o).Length)
                {
                    return false;
                }
            }
            // If the object passed is of type Jagged Array
            else
            {
                int i = 0;
                for (; i < ((Array)o).Length; i++)
                {
                    if (((Array)o).GetValue(i) != null && ((Array)o).GetValue(i).GetType().IsArray)
                    {
                        return true;
                    }
                    else if (((Array)o).GetValue(i) != null && !(((Array)o).GetValue(i).GetType().IsArray))
                    {
                        return false;
                    }
                    else if (((Array)o).GetValue(i) == null)
                    {
                        continue;
                    }
                }
                if (i == ((Array)o).Length)
                {
                    return false;
                }
            }

            return false;
            // return !(!o.GetType().IsArray && ((Array)o).Rank > 1);
        }
        /// <summary>allocate an arrayof passed dimensions dynamically. The Array.NewInstance method
        /// does not throw an error
        /// </summary>
        /// <param name="cl">The class of the array.</param>
        /// <param name="dims">The dimensions of the array.</param>
        /// <param name="dim">The index in the array</param>
        /// <returns>The allocated array.</returns>
        public static Array NewInstance(Type cl, int[] dims, int dim)
        {
            // suggested in .99 version:
            // Treat a scalar as a 1-d array of length 1
            if (dims.Length == 0)
            {
                dims = new int[] { 1 };
            }

            if (dim == dims.Length - 1)
            {
                return NewInstance(cl, dims[dim]);
            }
            else
            {
                Array a = new Array[dims[dim]];
                for (int i = 0; i < a.Length; ++i)
                {
                    a.SetValue(NewInstance(cl, dims, dim + 1), i);
                }

                return a;
            }
            /*
            Array o = Array.CreateInstance(cl, dims);
            if(o == null)
            {
              System.String desc = cl + "[";
              System.String comma = "";
              for(int i = 0; i < dims.Length; i += 1)
              {
                desc += comma + dims[i];
                comma = ",";
              }
              desc += "]";
              throw new System.OutOfMemoryException("Unable to allocate array: " + desc);
            }
            return o;
            */
        }
        /// <summary>Allocate an array dynamically. The Array.NewInstance method
        /// does not throw an error.</summary>
        /// <param name="cl"> The class of the array.</param>
        /// <param name="dims">The dimensions of the array.</param>
        /// <returns>The allocated array.</returns>
        /// <throws>An OutOfMemoryError if insufficient space is available.</throws>
        public static Array NewInstance(Type cl, int[] dims)
        {
            return NewInstance(cl, dims, 0);
        }
        /*
            /// <summary>Do the curling of the 1-d to multi-d array.</summary>
            /// <param name="input"> The 1-d array to be curled.</param>
            /// <param name="output">The multi-dimensional array to be filled.</param>
            /// <param name="dimens">The desired output dimensions.</param>
            /// <param name="offset">The current offset in the input array.</param>
            /// <returns>The number of elements curled.</returns>
            protected internal static int DoCurl(Array input, Array output, int[] dimens, int offset)
            {         
                if(dimens.Length == 1)
                {
                    Array.Copy(input, offset, output, 0, dimens[0]);
                    return dimens[0];
                }
         
                int total = 0;
                int[] xdimens = new int[dimens.Length - 1];
          Array.Copy(dimens, 1, xdimens, 0, xdimens.Length);
          for(int i = 0; i < dimens[0]; i += 1)
          {
            total += DoCurl(input, (Array)output.GetValue(i), xdimens, offset + total);
          }
                return total;
            }
        */
        /// <summary>Allocate an array dynamically. The Array.NewInstance method
        /// does not throw an error.</summary>
        /// <param name="cl"> The class of the array.</param>
        /// <param name="dim"> The dimension of the array.</param>
        /// <returns> The allocated array.</returns>
        public static Array NewInstance(Type cl, int dim)
        {
            Array o = Array.CreateInstance(cl, dim);
            if (o == null)
            {
                String desc = cl + "[" + dim + "]";
                throw new System.OutOfMemoryException("Unable to allocate array: " + desc);
            }
            return o;
        }
}

Related Tutorials