C# Copy Array by Value - c#

I have a typed array MyType[] types;
and i want to make and independant copy of this array. i tried this
MyType[] types2 = new MyType[types.Length] ;
types2 = types ;
but this create a reference to the first. I then tried
Array.Copy( types , types2 , types.Length ) ;
but I have the same problem: changing a value in the first array changes the value in the copy as well.
How can I make a completely independent or deep copy of an Array, IList or IEnumerable?

Based on the first post, all he needs is this for "an independent copy of the array". Changes to the shallowCopy array itself would not appear in the types array (meaning element assignment, which really is what he showed above despite saying "deep copy"). If this suits your needs, it will have the best performance.
MyType[] shallowCopy = (MyType[])types.Clone();
He also mentions a "deep copy" which would be different for mutable types that are not recursive value-type aggregates of primitives. If the MyType implements ICloneable, this works great for a deep copy:
MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());

For the impatient:
newarray = new List<T>(oldarray).ToArray();

Implement a clone method on MyType, using protected method MemberwiseClone (performs shallow copy) or using a deep cloning technique. You can have it implement an ICloneable then write several extensions methods that will clone the corresponsing collection.
interface ICloneable<T>
{
T Clone();
}
public static class Extensions
{
public static T[] Clone<T>(this T[] array) where T : ICloneable<T>
{
var newArray = new T[array.Length];
for (var i = 0; i < array.Length; i++)
newArray[i] = array[i].Clone();
return newArray;
}
public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T>
{
foreach (var item in items)
yield return item.Clone();
}
}
You must do this because while a new array is created when you use Array.Copy it copies the references, not the objects referenced. Each type is responsible for copying itself.

If your type is serializable you can use serialization techniques to get a copy of your array (including deep copies of the items):
private static object GetCopy(object input)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, input);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
To use it:
MyType[] items = new MyType[2];
// populate the items in the array
MyType[] copies = (MyType[])GetCopy(items);

I wanted to do the same thing: make a copy of an array by value for things like sorting so that I could later reinitialize another temp array with the original source array. After researching this, I found this cannot be done so simply. So, I made a workaround. I will use my own code below:
string[] planetNames = new string[] { "earth", "venus", "mars" };
string[] tempNames = new string[planetNames.Length];
for (int i = 0; i < planetNames.Length; i++)
{
tempNames[i] = planetNames[i];
}
planetNames is my source array. tempNames is the array which I will later sort independently of planetNames. I have tested this and this code does not sort planetNames when I sort tempNames which is what I was attempting to achieve.

If you want to create a copy of just an array with references to objects in old array (or if you have array of value type objects), simplest solution is
var newArray = oldArray.ToArray()
If you want deep copy you should have a method which copies single object of your type (e.g. public MyType Copy(MyType obj)). Then solution will look like
var newArray = oldArray.Select(x => Copy(x)).ToArray()

I've found if you just want a simple char array copy you can trick C# into doing a copy by value using the char:
char[] newchararray = new char[desiredchararray.Length];
for (int k = 0; k < desiredchararray.Length; k++)
{
char thecharacter = newchararray[k];
newchararray[k] = thecharacter;
oldchararray[k] = oldchararray[k] + 1;
}
Seems to work for me but if anyone disagrees please let me know :)

Copying the value of the array in this case are numbers
int[] arr = { 1, 2, 3, 4, 5 };
int[] copyArr = new int[arr.Length];
for (int i = 0; i <arr.Length; i++)
{
copyArr[i]=arr[arr.Length-i-1];
}
Console.WriteLine(string.Join(" ",arr));**

Related

Instantiation of every array element(class) - C# [duplicate]

Given a class:
class clsPerson { public int x, y; }
Is there some way to create an array of these classes with each element initialized to a (default) constructed instance, without doing it manually in a for loop like:
clsPerson[] objArr = new clsPerson[1000];
for (int i = 0; i < 1000; ++i)
objArr[i] = new clsPerson();
Can I shorten the declaration and instantiation of an array of N objects?
The constructor must be run for every item in the array in this scenario. Whether or not you use a loop, collection initializers or a helper method every element in the array must be visited.
If you're just looking for a handy syntax though you could use the following
public static T[] CreateArray<T>(int count) where T : new() {
var array = new T[count];
for (var i = 0; i < count; i++) {
array[i] = new T();
}
return array;
}
clsPerson[] objArary = CreateArray<clsPerson>(1000);
You must invoke the constructor for each item. There is no way to allocate an array and invoke your class constructors on the items without constructing each item.
You could shorten it (a tiny bit) from a loop using:
clsPerson[] objArr = Enumerable.Range(0, 1000).Select(i => new clsPerson()).ToArray();
Personally, I'd still allocate the array and loop through it (and/or move it into a helper routine), though, as it's very clear and still fairly simple:
clsPerson[] objArr = new clsPerson[1000];
for (int i=0;i<1000;++i)
clsPerson[i] = new clsPerson();
If it would make sense to do so, you could change class clsPerson to struct Person. structs always have a default value.

How to deep copy array items with unknown type at runtime without using MakeGenericMethod?

I got an System.Object (AKA object) that is simple one-dimensional array (I do a lot of checks). The element type will become known at runtime. I have to do two types of copying the array:
1) deep copy array itself but shallow copy items:
- this has answer here: my previous question
2) deep copy array itself as well as its items:
I did it like that:
public object FullDeepCopy_SimpleArray(object original)
{
Type elementType = original.GetType().GetElementType();
return GetType()
.GetMethod("Create_DeepCopyArray")
.MakeGenericMethod(elementType)
.Invoke(this, new object[] { original });
}
//used in generic invoke
public T[] Create_DeepCopyArray<T>(object original)
{
T[] origArray = (T[])((Array)original).Clone();
int length = origArray.Length;
T[] copy = (T[])(Array.CreateInstance(typeof(T), length));
for (int i = 0; i < length; i++)
{
copy[i] = (T)Create_infDeep_CopyOf(origArray[i]); // this makes the deep copy of any item
}
return copy;
}
It works perfectly but it raises some problems:
it's unsecure to work with, other programmers might delete the method Create_DeepCopyArray as it is only used in GetMethod code and IDE Visual Studio doesn't recognize it as used (because it's passed as string)
Look at the number of casts in Create_DeepCopyArray method, I kind of think there must be a better solution
Do you have any ideas to improve this?

C# - How to create temporary value that does not change original value [duplicate]

I have a typed array MyType[] types;
and i want to make and independant copy of this array. i tried this
MyType[] types2 = new MyType[types.Length] ;
types2 = types ;
but this create a reference to the first. I then tried
Array.Copy( types , types2 , types.Length ) ;
but I have the same problem: changing a value in the first array changes the value in the copy as well.
How can I make a completely independent or deep copy of an Array, IList or IEnumerable?
Based on the first post, all he needs is this for "an independent copy of the array". Changes to the shallowCopy array itself would not appear in the types array (meaning element assignment, which really is what he showed above despite saying "deep copy"). If this suits your needs, it will have the best performance.
MyType[] shallowCopy = (MyType[])types.Clone();
He also mentions a "deep copy" which would be different for mutable types that are not recursive value-type aggregates of primitives. If the MyType implements ICloneable, this works great for a deep copy:
MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());
For the impatient:
newarray = new List<T>(oldarray).ToArray();
Implement a clone method on MyType, using protected method MemberwiseClone (performs shallow copy) or using a deep cloning technique. You can have it implement an ICloneable then write several extensions methods that will clone the corresponsing collection.
interface ICloneable<T>
{
T Clone();
}
public static class Extensions
{
public static T[] Clone<T>(this T[] array) where T : ICloneable<T>
{
var newArray = new T[array.Length];
for (var i = 0; i < array.Length; i++)
newArray[i] = array[i].Clone();
return newArray;
}
public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T>
{
foreach (var item in items)
yield return item.Clone();
}
}
You must do this because while a new array is created when you use Array.Copy it copies the references, not the objects referenced. Each type is responsible for copying itself.
If your type is serializable you can use serialization techniques to get a copy of your array (including deep copies of the items):
private static object GetCopy(object input)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, input);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
To use it:
MyType[] items = new MyType[2];
// populate the items in the array
MyType[] copies = (MyType[])GetCopy(items);
I wanted to do the same thing: make a copy of an array by value for things like sorting so that I could later reinitialize another temp array with the original source array. After researching this, I found this cannot be done so simply. So, I made a workaround. I will use my own code below:
string[] planetNames = new string[] { "earth", "venus", "mars" };
string[] tempNames = new string[planetNames.Length];
for (int i = 0; i < planetNames.Length; i++)
{
tempNames[i] = planetNames[i];
}
planetNames is my source array. tempNames is the array which I will later sort independently of planetNames. I have tested this and this code does not sort planetNames when I sort tempNames which is what I was attempting to achieve.
If you want to create a copy of just an array with references to objects in old array (or if you have array of value type objects), simplest solution is
var newArray = oldArray.ToArray()
If you want deep copy you should have a method which copies single object of your type (e.g. public MyType Copy(MyType obj)). Then solution will look like
var newArray = oldArray.Select(x => Copy(x)).ToArray()
I've found if you just want a simple char array copy you can trick C# into doing a copy by value using the char:
char[] newchararray = new char[desiredchararray.Length];
for (int k = 0; k < desiredchararray.Length; k++)
{
char thecharacter = newchararray[k];
newchararray[k] = thecharacter;
oldchararray[k] = oldchararray[k] + 1;
}
Seems to work for me but if anyone disagrees please let me know :)
Copying the value of the array in this case are numbers
int[] arr = { 1, 2, 3, 4, 5 };
int[] copyArr = new int[arr.Length];
for (int i = 0; i <arr.Length; i++)
{
copyArr[i]=arr[arr.Length-i-1];
}
Console.WriteLine(string.Join(" ",arr));**

Generically accessing multidimensional arrays in C#

C# allows creating and populating multidimensional arrays, here is a simple example:
public static void Main(String[] args)
{
var arr = (int[,])CreateArray(new [] {2, 3}, 8);
Console.WriteLine("Value: " + arr[0,0]);
}
// Creates a multidimensional array with the given dimensions, and assigns the
// given x to the first array element
public static Array CreateArray<T>(int[] dimLengths, T x)
{
var arr = Array.CreateInstance(typeof(T), dimLengths);
var indices = new int[dimLengths.Length];
for (var i = 0; i < indices.Length; i++)
indices[i] = 0;
arr.SetValue(x, indices); // Does boxing/unboxing
return arr;
}
This works well. However, for some reason there is no generic version of Array.SetValue(), so the code above does boxing/unboxing, which I'd like to avoid. I was wondering if I missed something or if this is an omission in the .NET API?
No, you are not missing anything: Arrays does not have an option that sets the value without boxing and unboxing.
You do have an alternative to this with LINQ, but it is probably going to be slower than boxing/unboxing for a single element, because compiling a dynamic lambda would "eat up" the potential benefits:
public static Array CreateArray<T>(int[] dimLengths, T x) {
var arr = Array.CreateInstance(typeof(T), dimLengths);
var p = Expression.Parameter(typeof(object), "arr");
var ind = new Expression[dimLengths.Length];
for (var i = 0; i < dimLengths.Length; i++) {
ind[i] = Expression.Constant(0);
}
var v = Expression.Variable(arr.GetType(), "cast");
var block = Expression.Block(
new[] {v}
, new Expression[] {
Expression.Assign(v, Expression.Convert(p, arr.GetType()))
, Expression.Assign(Expression.ArrayAccess(v, ind), Expression.Constant(x))
, Expression.Constant(null, typeof(object))
}
);
Expression.Lambda<Func<object, object>>(block, p).Compile()(arr);
return arr;
}
If you wanted to set all elements in a loop, you could modify the above to compile a dynamically created lambda with multiple nested loops. In this case, you could get an improvement on having to perform multiple boxing and unboxing in a series of nested loops.
for some reason there is no generic version of Array.SetValue()
While it is definitely possible to write a generic method similar to SetValue in the Array class, it may not be desirable. A generic method on a non-generic class would give a false promise of compile-time type safety, which cannot be guaranteed, because the compiler does not know the runtime type of the Array object.
I didn't find any generic ways either to set a value into an Array instance, so I guess the only workaround is to use the unsafe context to avoid boxing.
However, there can be no generic version, now when I think of it. See, when you define a generic method method<T>()..., you do define the parameter for the method: ...<T>(T[] a)... where you have to be specific about the dimensions count, which is one. To create a twodimensional parameter, you define it like this ...<T>(T[,] a)... and so on.
As you can see, by the current syntax of C#, you simple cannot create a generic method, which can accept any-dimensional array.

Adding to an Array

I have an array:
String[] ay = {
"blah",
"blah number 2"
"etc" };
... But now I want to add to this array at a later time, but I see no option to do so. How can this be done? I keep getting a message saying that the String cannot be converted to String[].
Thank you
Use a List rather than an array:
List<string> list = new List<string>();
list.Add( "blah" ) ;
Then, later, if you really do need it as an array:
string[] ay = list.ToArray();
Arrays are of fixed size, so after it has been created, you can't change the size of it (without creating a new array object)
Use the List<string> instead of the array.
Arrays can't change their size after they are declared. Use collections instead. For example: List.
As everyone's already said, use List in the System.Collections.Generic namespace.
You could also use a Hashtable which will allow you to give each string a meaning, or "key" which gives you an easy way to pull out a certain string with a keyword. (as for keeping messages stored in memory space for whatever purpose.)
You could also Create a new array each time you add a value, make the new array 1 bigger than the old one, copy all the data from the first array into the 2nd array, and then add your new value in the last slot (Length - 1)
Then replace the old array with your new one.
It's the most manual way of doing it.
But List and Hashtable work perfectly well too.
If you don't need indexing a specific array element (usage of brackets), but you want to be able to efficiently add or remove elements, you could use LinkedList.
If you do need indexing
have a look at Dictionary data type also in the System.Collection
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
so you could do something like
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "afljsd");
You can do this but I don't recommend it:
// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
// oldArray the old array, to be reallocated.
// newSize the new array size.
// Returns A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray;
}
Here's an extension method to add the to arrays together and create a new string array
public static class StringArrayExtension
{
public static string[] GetStringArray (this string[] currentArray, string[] arrayToAdd)
{
List<String> list = new List<String>(currentArray);
list.AddRange(arrayToAdd);
return list.ToArray();
}
}

Categories