How to make a shallow copy of an array? - c#

I pass a two-dimensional array as a property to my user control. There I store this values in another two-dimensional array:
int[,] originalValues = this.Metrics;
Later, I change values in this.Metrics. But now if I retrieve values from originalValues, I get the changed values from this.Metrics. How do I make a copy of the elements of this.Metrics and don't just get the reference of the array?

I don't know where I got this from, but this works well for me.
public static class GenericCopier<T> //deep copy a list
{
public static T DeepCopy(object objectToCopy)
{
using (MemoryStream memoryStream = new MemoryStream())
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, objectToCopy);
memoryStream.Seek(0, SeekOrigin.Begin);
return (T)binaryFormatter.Deserialize(memoryStream);
}
}
}

You can clone an array, which makes a copy of it:
int[,] originalValues = (int[,])this.Metrics.Clone();

The crux of your problem is here:
There I store this values in another two-dimensional array
This is actually inaccurate. You are not creating a new array; you are setting your originalValues variable to the same array. For a more detailed explanation, see below.
The confusion expressed in the comments to Pieter's answer is due to some uncertainty surrounding the term "deep copy."
When it comes to copying objects, there's deep copying and shallow copying.
Deep copying involves making a copy of all the data belonging to an object, which means that if the object includes members which are themselves complex (for example, instances of user-defined reference types), those objects must be deep-copied as well (along with all of their members, and so on).
Shallow copying involves simply copying all of the fields from one object to another, which means that if the object includes reference types, only the references need to be copied (and so the copied references will be pointing to the same objects).
In the case of the code you've posted:
int[,] originalValues = this.Metrics;
... there's actually no copying of any objects at all. All you've done is copied a single reference, assigning the value of this.Metrics (a reference) to the variable originalValues (also a reference, to the very same array). This is essentially the same as a simple value assignment, like this:
int x = y; // No objects being copied here.
Now, the Array.Clone method makes, in fact, a shallow copy. But as Pieter pointed out, there's really no difference between a "shallow" or "deep" copy of an array of integers, since integers are not complex objects.
If you had something like this:
StringBuilder[,] builders = GetStringBuilders();
StringBuilder[,] builderCopies = (StringBuilder[,])builders.Clone();
..., you'd end up with a whole new array (a copy, yes), but one containing all of the same StringBuilder objects (so a shallow copy). This is where deep versus shallow copying comes into play; if you wanted a new array containing copies of all of the StringBuilder objects from builders, you'd need to make a deep copy.

If the object you are copying is an array, then you can use:
Array.Copy(sourceArray, destinationArray, sourceArray.Count)
This will give you a separate copy of the original array into your destination array.

If you want to deep copy an array of reference types, you can do this methodology:
Implement IClonable iterface for your class and do your deep copy of all value typed fields inside to another constructed object.
class A: ICloneable {
int field1;
public object Clone()
{
A a= new A();
//copy your fields here
a.field1 = this.field1;
...
}
}
Then you can do the actual copy using
A[] array1 = new A[]{....};
A[] array2 = array1.Select(a => a.Clone()).ToList();

IClonable is great but unless you IClonable every type in your top level cloned type, you end up with references, AFAIK.
Based on that, unless you want to walk the object and clone each object within, this seems the simplest approach.
It's simple and guarantees a clean break from references of deep objects in the original:
using Newtonsoft.Json;
private T DeepCopy<T>(object input) where T : class
{
var copy = JsonConvert.SerializeObject((T)input); // serialise to string json object
var output = JsonConvert.DeserializeObject<T>(copy); // deserialise back to poco
return output;
}
Usage:
var x = DeepCopy<{ComplexType}>(itemToBeCloned);
Where ComplexType is anything wanting a break from references.
It takes any Type in, stringifies it, then de-stringifies to a new copy.
Best use example:
If you've selected a complex type as a result of a lambda query and want to modify the result without affecting the original.

You can deepcopy a 1d array using LINQ.
var array = Enumerable.Range(0, 10).ToArray();
var array2 = array.Select(x => x).ToArray();
array2[0] = 5;
Console.WriteLine(array[0]); // 0
Console.WriteLine(array2[0]); // 5
With 2d array, this will not work because 2d array doesn't implement IEnumerable.

You need to create a new array. You then need to manually copy the value of each element into the new array. What you are doing in the example given is to create two array variables which both reference the same array.
The problem with the clone method is that it is a shallow copy. In this isntance, because you are using int, it does not mater. Howver, if you had an array of classes the definition of the ICLonable interface leaves it ambiguous as to how deep the clone will go.
Imagine if you had a class that has properties that are other classes which has properties that are other classes. The clonable interface does not state whether it will also clone the sub members or not. Moreover, many people have different views on what the expected behaviour is.
Hence this is why it is often recommended to define two interfaces, IShallowCopy and IDeepCopy.

Here is a fast solution that is almost similar than some answers here, but which mention MemberwiseClone.
I have POCO classes that only contains reference values.
public class MyPoco {
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
// Add a "Clone" method.
public MyPoco Clone() {
return (MyPoco)this.MemberwiseClone();
}
}
Then use LINQ to build a new array of clones:
var myClone = MyPocoArray.Select(x => x.Clone).ToArray();

Related

Compare two array of object without knowing their type

I need your help ! I would like to compare two array of object. These arrays should be identical but not equally ordered.
Context :
I'm writing a function to compare to object tree of the same type. By reflection I check each property of first object with the second object, when :
I find a primitive type I compare it and if a difference is found i
keep it in a list
I find an object, I call the method (recursively) on the two objects
I find an array, I check the length if they are the same, I parse the
array and compare each value with the method (recursively). In this case I need to order the arrays to be sure the object are in the same order.
Way I think of, but not realizable :
I can't override the equals method of the classes, there is to many
classes and they are auto generated by a tool based on an XSD file.
I tried to use the GetHashCode in an IComparer interface, but the
GetHashCode work with the references, then the ordering has no sense.
Do you have an idea of how I can proceed with it ? I'm thinking of generating an HashCode based on the content but how can I do it generically ?
Thanks for your help.
I found this solution...
I implemented a IComparer, and compare my object from stream transformed in Strings (not so elegant but it workd well) :
private class ObjectStreamComp : IComparer
{
public int Compare(Object x, Object y )
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream mx = new MemoryStream())
using (MemoryStream my = new MemoryStream())
{
binaryFormatter.Serialize(mx, x);
binaryFormatter.Serialize(my, y);
mx.Position = 0;
my.Position = 0;
return (new StreamReader(mx)).ReadToEnd().CompareTo((new StreamReader(my)).ReadToEnd());
}
}
}
I can use serialization, because my object tree is marked Serialized (for XML serialization).
I use it like that :
Array.Sort(valueReferenceArray, ((IComparer)new ObjectStreamComp()));
Array.Sort(valueCreatedArray, ((IComparer)new ObjectStreamComp()));
In that case you can implement you own IEqualityComparer
public class MyComparer<T> : IEqualityComparer<T> where T : class
{
public bool Equals(T x, T y)
{
//your code here
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
}
And for example if you wanted to use it in exept you simply do this
var list1 = new List<object>();
var list2 = new List<object>();
var rest = list1.Except(list2, new MyComparer<object>());
You know that comparing two object trees using reflection only will get you into trouble if performance ever gets an issue? You should always try to avoid reflection whereever possible, especially if you are dealing with large object trees. Reflection is OK for a proof-of-concept, but not really for more.
But what is wrong with overriding the Equals-Method? XSD usually does not generate you Equals-methods and thus you are free to extend these generated classes with your own stuff using partial classes. This is exactly what partial classes have been created for, to mic static and generated code more easily.
Edit: Note that if you override Equals, you also have to override GetHashCode appropriately. However, this means that all objects using your classes will use value equality by default. If this is not what you want, a custom IEqualityComparer as suggested by Alex Pashkin is a better option.

C# Value Type Lists

I'm a bit confused. Structs are more or less value types that get constructed on the stack and therefore have a straightforward lifetime.
When building a list with a struct, you cannot modify them directly because the returned value is a copy, and won't actually modify the item stored in the list.
My confusion comes here: Why can I not directly change a struct item in a list, but I can directly access and modify the base value types (int, float, etc...)?
This works:
List<int> foobar1 = new List<int>();
foobar1.Add(1);
foobar1[0] = 2;
This Doesn't:
public struct foo
{
public int bar;
}
...
List<foo> foobar2 = new List<foo>();
foobar2.Add(new foo());
foobar2[0].bar = 2;
The two are fundamentally different, and not just because someone decided that it is, let me explain.
The first piece of code replaces wholesale the int value in the 0th element position in the list. It doesn't matter which int value is there, afterwards the list contains the int value 2 in the 0th position.
The second piece of code, however, is attempting to replace parts of the struct. Yes, I know, the struct only has one field but the compiler makes no such distinction. You're effectively modifying a copy of the struct retrieved from the list. This is not allowed.
So the first piece of code just stuffs a new value type into the list, the second piece of code tries to modify the value type from the list, which is a copy.
So, can you change the second piece of code to be like the first, ie. replace the element in the list completely?
Sure:
var temp = foobar[0];
temp.bar = 2;
foobar2[0] = temp; // no longer modifies the copy, but replaces the element
Basically, this right here:
foobar2[0].bar = 2;
^ ^
| |
is the problem.

LINQ Select Many - Modify flattened collection

I have a class named ACTIVITY. This class contains a list of Laps, and each Lap has a collection of TRACPOINTS.
ACTIVITY --many--> LAPS ---many --> TRACPOINTS.
Whenever I fLatten the TRACPOINTS collection I get the list of all the TRACPOINTS. But when I modify those of course the originals don't get modified since it's a copy.
Is there any way that whatever change I made to the flattened tracpoints gets changed in the Tracpoints list for each lap?
As long as TRACPOINT is a struct, it is not possible in any reasonable way.
Whenever you assign a value of struct variable or field to another variable or field, its contents are copied. The same holds for passing it as a method argument or returning it from a method, its value is copied. This is value semantics [1]. Compare this to atomic types like int, which have value semantics too. You would probably expect the following code to print 2, not 3.
static function Change(int j) { j = 3; }
static void Main(string[] args) {
int i = 2;
Change(i);
System.Console.WriteLine(i);
}
If you do SelectMany, each value from the collection is probably assigned to some temporary local variable and then returned from the iterator (SelectMany), therefore it is copied and in fact possibly copied many times before it comes out from the iterator. So what you are updating is a copy of the struct. Like in the example, you're not changing variable i, but its copy stored in variable j.
This is why structs should be immutable. Instead of having properties with getters and setter in your struct, they should have only getters. For changing values of properties of a struct, you can implement methods that copy the whole original struct, change the value of the desired property and return the new struct instance. In fact, again, its copy will be returned. Example:
struct S {
int f;
public int F { get { return this.f; } }
public S SetF(int newVal) {
var s = new S();
s.f = newVal;
return s;
}
}
var x = new S();
x = x.SetF(30);
That said, it could be possible to achieve what you want with pointers and unsafe C#, but believe me, it will be way easier to change your structs to classes, so that they have reference semantics instead of value semantics, or keep them structs, but make them immutable and do not use Linq, but old school loops. If you want to use Linq for something like SelectMany in such scenario, you probably do not care about performance difference between structs and classes so much...
[1] http://msdn.microsoft.com/en-us/library/aa664472(v=vs.71).aspx

C# passing parameters by reference

I have the below piece of code which Prefixs a string to the start of each member of a string array. ie. ["a","b","c"] prefixed with "z" becomes ["za","zb","zc"].
private string[] Prefix(string[] a, string b) {
for(int i = 0;i < a.Length;i++) {
a[i] = b + a[i];
}
return a;
}
The function works fine (although if theres a better way to do this, I'm happy to hear it), but I'm having issues when passing parameters.
string[] s1 = new string[] {"a","b"};
string[] s2 = Prefix(s1,"z");
Now as far as I can tell, I'm passing s1 by Value. But when the Prefix function has finished, s2 and s1 have the same value of ["za,"zb"], or s1 has been passed by reference. I was certain you had to explicitly declare this behaviour in c#, and am very confused.
As others have said, the reference is passed by value. That means your s1 reference is copied to a, but they both still refer to the same object in memory. What I would to do fix your code is write it like this:
private IEnumerable<string> Prefix(IEnumerable<string> a, string b) {
return a.Select(s => b + s);
}
.
string[] s1 = new string[] {"a","b"};
string[] s2 = Prefix(s1,"z").ToArray();
This not only fixes your problem, but also allows you to work with Lists and other string collections in addition to simple arrays.
C#, like Java before it, passes everything by value by default.
However, for reference types, that value is a reference. Note that both string and array are reference types.
Here's a better way to do it:
private string[] Prefix(string[] a, string b) {
return a.Select(s => b + s).ToArray();
}
or even:
private IEnumerable<string> Prefix(IEnumerable<string> a, string b) {
return a.Select(s => b + s);
}
You are passing the reference to s1 by value. In other words, your a parameter (when in the Prefix function scope), and your s1 variable, are references to the same array.
strings are immutable
this means that when you append a string to a string you get out a totally new string - its for performance reasons. its cheaper to make a new string that to reallocate the existing array.
hence why it feels like you are working with strings by value
in c# all reference types are passed by reference by default - ie classes creaped on the heap rather than values.
Actually, a reference to s1 was passed by value to Prefix(). While you now have two different references, both s1 and s2 still refer to the same string array, as arrays are reference types in C#.
Passing by value doesn't mean that you can't change things.
Objects are passed by value, but the value is (effectively) a pointer to the object.
Arrays are objects and a pointer to the array gets passed in. If you change the contents of the array in a method, the array will reflect the changes.
This doesn't happen with strings only because strings are immutable - once constructed, their contents can't change.
A reference to the string array is passed by value.
Consequently, the original array reference in the calling method cannot be changed, meaning that a = new string[10] within the Prefix method would have no impact on the s1 reference in the calling method. But the array itself is mutable, and a duplicate reference to the same array is capable of making changes to it in a way that would be visible to any other reference to the same array.
The value of an object is passed. For "reference" objects this is the value of the reference. A clone/copy/duplicate of the underlying data is not made.
To fix the issue observed, simply don't mutate the input array -- instead, create a new output array/object and fill it in appropriately. (If you must use arrays, I would likely use this approach as it's so boringly C-like anyway.)
Alternately, you can clone the input array first (which also creates a new object). Using a clone (which is a shallow copy) in this case is okay because the inner members (strings) are themselves immutable -- even though they are reference types the value of the underlying object can't be changed once created. For nested mutable types, more care may need to be taken.
Here are two methods which can be used to create a shallow copy:
string[] B = (string[])A.Clone();
string[] B = (new List<string>(A)).ToArray();
It's not inclusive.
Personally though, I would use LINQ. Here is a teaser:
return a.Select(x => b + x).ToArray();

Not able to modify object of struct in loop

I have a List of structure.In the loop i am trying to modify the object's property,which is happening,but when i (Quick look in Visual studio)look into the list object ,the new value is not reflecting.Is it by virtue that the structure's object cannot be modified when in a collection?
I am using generics list with the struct as the type in the list
You mention "modify the object's property" in the context of a struct, but importantly a struct is not an object. Other people have answered as to the issue with structs being copied (and changes discarded), but to take that further the real problem here is that you have a mutable (changeable) struct at all. Unless you are on XNA (or similar) there is simply no need.
If you want to be able to change properties, make it a class:
public class Foo {
public string Bar {get;set;}
}
This is now a reference-type, and your changes (obj.Bar = "abc";) will be preserved through the foreach. If you really want/need a struct, make it immutable:
public struct Foo {
private readonly string bar;
public string Bar { get {return bar; }}
public Foo(string bar) {this.bar = bar;}
}
Now you can't make the mistake of changing the value of a copy; you would instead have to use the indexer to swap the value (list[i] = new Foo("abc");). More verbose (and you can't use foreach), but correct.
But IMO, use a class. Structs are pretty rare, to be honest. If you aren't sure: class.
If you are using a foreach loop you probably got
Compiler Error CS1654
Error Message Cannot modify members of
'variable' because it is a 'read-only
variable type'
This error occurs when you try to
modify members of a variable which is
read-only because it is in a special
construct.
One common area that this occurs is
within foreach loops. It is a
compile-time error to modify the value
of the collection elements. Therefore,
you cannot make any modifications to
elements that are value types,
including structs.
You could however try
struct MyStruct
{
public int i;
}
List<MyStruct> list = new List<MyStruct>
{ new MyStruct { i = 1 }, new MyStruct { i = 2 } };
for(int i = 0; i < list.Count; i++)
{
MyStruct val = list[i];
val.i++;
list[i] = val;
}
EDIT
See also Structs Tutorial
Structs vs. Classes
Structs may seem similar to classes,
but there are important differences
that you should be aware of. First of
all, classes are reference types and
structs are value types.
I THINK i know what the problem might be.
struct Astruct
{
int amember;
}
List < Astruct > listofStructs;
foreach(Astruct A in listofStructs)
{
A.amember = 1337;
}
if this is what you are doing...
when you use structs in c# they are not referenced but copied! so that means the contents of your list is being COPIED to A, so when you change A it doesn't change the value in the list!
to solve this problem (if this is your problem...) either use CLASSES rather than STRUCTS, that way A would be a reference, OR use a manual iterating for loop instead, ie:
for(int i=0;i < listofStructs.Count;i++)
{
listofStructs[i].amember = 1337;
}
alternatively, if you’re using a list, you maybe should use an iterator or something... but the above should definitely fix that problem.
Given the information in your post (although I'd have liked to see the code itself), let me put forth the most probable issue and its fix.
foreach(var s in listOfStructs)
{
s.Property = x;
}
s is assigned to a copy of the actual struct in the collection. s.set_Property is now modifying the copy which is thrown away at the end of the current iteration.
This is because 2 value type variables cannot point to the same instance.
struct1 = new MyStruct(100, 200);
struct2 = struct1; // struct2 is now a copy of struct1
Now to the problem of how do you modify the instances in a collection:
Get the object to modify in a local variable (copy created). Modify it. Now remove the original object and insert the copy. use listOfStructs[i] = modifiedInstance.

Categories

Resources