Class1 : IClass
{
// ...
}
List<IClass> newList = new List<IClass>();
Class1 obj1 = new Class1();
newList.Add(obj1);
I have list of references, right? Now, the new object comes up. For example obj2 which is an instance of Class1 as well. I would like to assign obj2 to obj1 using reference available on the list(note! I can't access obj1 directly). How could I do it?
I assume you mean that you want obj2 to point to the same value that obj1 originally pointed to. If so then just grab the value out of the list with the indexer
Class1 obj2 = (Class1)newList[0];
Note that I had to insert a cast there. The type of elements in the list is IClass1 but you specified obj2 as Class1.
Another option is to use LINQ to find the exact object you need from the list, if for instance obj1 wasn't the first item:
Class1 obj2
= (Class1)newList.SingleOrDefault(x => x.SomeUniquePropertyOfClass1 == someId);
You might have to compare multiple properties in your object, but I don't know what Class1 looks like.
What he/she means is that you have Object1, Object2(both of the same class) and List of Objects.
List1 points to Object1 and the question is, how to make Object1 point to Object2 using reference from the list.
newList[0] = obj2
would only change the reference on the list, however obj1 would stay immutable.
Related
Hi I have a list of objects(list1) and I'd like to make a copy of this list but I want that the objects in the second list(list2) to not be linked to the one in first list.
this is what I do
list<Obj> list1 = new list<Obj>{};
// I fill the list1 with objects Obj
// now I want to make a deep copy this is what I do
list<Obj> list2 = new list<Obj>(list1);
// but when I edit an object in list 1 I also edit the object in list2
I'd like to be able to edit the objects in list1 without edititng the object in list2,how can I get that???
thanks for your answers
You should implement the ICloneable interface in your Obj class. After that, you can call this code to create your second list:
list<Obj> list2 = new list<Obj>(list1.Select(x => x?.Clone()));
It will clone every item in the list. (With null-check)
You could add a copy constructor to your Obj.
Then loop through list1 create a new instance of your objects using the copy constructor and add it to list2.
Example:
Copy constructor:
public Obj(Obj copyFrom)
{
this.field1 = copyFrom.field1;
.
.
}
With the following LINQ query you have a one liner to use the above contructor:
list2.AddRange(list1.Select(s => new Obj(s)));
can some one explain to me how to break the chain with a NEW statement?
Let me clarify the chain I’m talking about. When I call to a class I use the NEW statement like so
Myclass x =new Myclass();
My understanding is this creates a new empty instance of Myclass. Now correct me if I’m wrong but having a new empty instance one should be able to add what ever data the class supports?
I use this lot and would think the above to be true until adding data in such a manner
Myclass x =new Myclass();
//oldMyclass being old data that needs to be changed then
//added back to the class as a new or duplicate entry
x = oldMyclass[1];
//we change the data
x.red= 0x54;
//we add it back
oldMyclass.add(x);
All is good until we edit the data after adding it say we need to change another value.
We access the oldMyclass and select the proper item say its index is 2 but we only want to change the values of index 2
Myclass x =new Myclass();
x = oldMyclass[2];
x.red=soemvalue;
oldMyclass[2] = x;
This will change the red value of both index 1 and index 2. How can I break the chain between index 1 and index 2?
I think I might have over simplified this question let me know.
Thanks for any information.
Edit: Here is the copy method that I tried
public static Items.SavedItem Copy(Items.SavedItem old)
{
Items.SavedItem x = new Items.SavedItem();
x.generator = old.generator;
x.hireling_class = old.hireling_class;
x.id = old.id;
x.item_slot = old.item_slot;
x.owner_entity_id = old.owner_entity_id;
x.socket_id = old.socket_id;
x.square_index = old.square_index;
x.used_socket_count = old.used_socket_count;
return x;
}
So let's say, for arguments sake, you have a class like this:
public MyClass
{
public string Foo { get; set; }
}
And you have a collection
List<MyClass> myList = new List<MyClass>();
Now you create an instance of MyClass
MyClass obj1 = new MyClass() { Foo = "bar" };
Now if you do this:
myList.Add(obj1);
myList.Add(obj1);
You now have a list with TWO members, but they happen to be the same object. Whats stored in the list is a reference to the object you added, not the object itself. So myList[0] == myList[1]
Now if you did this:
MyClass item = myList[1];
And then:
item.Foo = "something else";
Both the item at index 1 and the item at index 0 will have 'Foo == "something else"' because they are the same item.
Another point that seems to be confusing you is this: myList has two items. If I do this:
MyClass item = myList[0];
myList still has two items. Indexing a collection doesn't remove it and because of that, there is no need to add the item back to the list. It's already there. All I've done is copy the reference from myList to a variable named item.
There are collections (Stack and Queue for example) that do work on the principle that you will remove items and (potentially) add them back, but List doesn't work that way.
So if you wanted to add multiple objects to myList you need to create multiple objects with the new keyword. For example:
List<MyClass> myList = new List<MyClass>();
MyClass obj1 = new MyClass() { Foo = "bar" };
myList.Add(obj1);
obj1 = new MyClass() { Foo = "something else" }; // Note: I've reused the variable, but this is a *new* object
myList.Add(obj1);
Or, if you don't need the new object assigned to a variable, you can simply if to:
List<MyClass> myList = new List<MyClass>();
myList.Add(new MyClass() { Foo = "a" });
myList.Add(new MyClass() { Foo = "b" });
Or even more compactly, you can exploit the collection initialization syntax and simply:
List<MyClass> myList = new List<MyClass>()
{
new MyClass() { Foo = "a" },
new MyClass() { Foo = "b" }
}
If you want to copy an object from your list, then you need to copy each property (and if it contains other objects, you may need to copy them too). There are various ways to do this, IClonable or a copy constructor are examples, but it basically comes down to, at some point, doing something like this:
myCopy.Foo = myOriginal.Foo;
myCopy.Bar = myOriginal.Bar;
// repeat for all properties that you want to copy.
Now assuming that Foo and Bar aren't also reference types, you have a copy. If they are reference types, you have a copy, but myCopy.Foo and myOriginal.Foo are still pointing at the same object.
I have two ObservableCollection objects and obj1 has attach to collection change event. Obj1 has a value from obj2 by obj1 = obj2. When I add any item on obj2 it execute collection changed event of object 1. I could not understand why this is happening.
public MainWindow()
{
InitializeComponent();
ObservableCollection<int> obj1 = new ObservableCollection<int>();
ObservableCollection<int> obj2 = new ObservableCollection<int>();
obj1 = obj2;
obj1.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(obj1_CollectionChanged);
obj2.Add(1);
}
void obj1_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
MessageBox.Show("Testing");
}
obj1 and obj2 refer to the same object. The code above creates two objects in memory, but the line
obj1 = obj2;
changes the reference of obj1 to the object referenced by obj2.
This means that the CollectionChanged event is registered on the object which obj1 and obj2 refer to.
obj1 = obj2 doesn't give you a copy of obj2 in obj1. With this line you say 'obj1 please point to the same ObservableCollection as obj2'. The ObservableCollection that has been attached to obj1 before will be destroyed and both variables point to the same thing afterwards.
If you want a copy create a new ObservableCollection and fill in the other collection.
obj1 = new ObservableCollection(obj2);
You have only one ObservableCollection cause you override the reference of the variable obj1 by assign the references of obj2.
Your code:
obj1 = obj2;
Since then both variables point to the same ObservableCollection. After that assignment it is the same if you use variable obj1 or obj2 to call methods or register events on the ObservableCollection.
For some reason I cannot seem to identify what I am doing wrong. I have tried a few things and each time the original record is modified.
I have a list of a particular class. I am iterating through the list, if a specific condition is met, I need to create a duplicate item for this iteration, modify 2 values, then add it to the final list. Except everytime I modify the duplicate I created, the values are modified in the original. The data is a binding list that is set to a list.
// MyClasses is a BindingList<MyClass>
List<MyClass> classesToSave = new List<MyClass>();
foreach (var class in MyClasses)
{
classesToSave(class);
if (class.NeedsDupe)
{
MyClass dupeClass = new MyClass();
dupeClass = class;
dupeClass.NeedsDupe = false;
dupeClass.IsDupe = true;
classesToSave(dupeClass);
}
}
Lets say that through the first iteration, the first item in MyClasses has class.NeedsDupe == true and class.IsDupe == false. When class is added to classesToSave before the condition is hit, the only entry in classesToSave is the original class (class.NeedsDupe == true and class.IsDupe == false). However, when the condition is hit and the dupeClass object is modified and before dupeClass is added to classesToSave, the original entry (and only entry) in classesToSave is then modified.
Am I missing something completely? I have a feeling that I am drawing a brain fart and maybe need a reference to the old object? Or am I somehow copying the properties of the BindingList and when I change the dupeClass object that I think is a new object I am actually causing the change to ripple back through?
Thanks for any help.
That's the nature of classes, they are reference type. Create a copy constructor for MyClass
class MyClass
{
public MyClass(MyClass myClass)
{
//Assign the properties here
//this.x = myClass.x;
//....
//....
}
}
then you call
MyClass dupeClass = new MyClass(#class);
The following lines are problematic. dupeclass references the class; they point to the same object. Instead of making them equal, set the properties of dupeClass equal to the properties of class.
MyClass dupeClass = new MyClass();
dupeClass = class;
In this line you're creating a new instance of MyClass:
MyClass dupeClass = new MyClass();
but then you're immediately overwriting it with the original:
dupeClass = class;
from then on, dupeClass and class are both referencing the same object, so changes to dupeClass are also made to class.
you are creating a new instance and then assigning the old one to it
MyClass dupeClass = new MyClass();
dupeClass = class;
UPDATE
You have to either copy the properties by hand or use Reflection
foreach (var property in oldObject.GetType().GetProperties())
{
var prop= newObject.GetType().GetProperty(property.Name);
if (prop!= null)
prop.SetValue(newObject, property.GetValue(oldObject));
}
Let's say I have a list of objects and that I'm extracting and modifying an item from the list like this:
List<MyObject> TheListOfObjects = new List<MyObject>();
MyObject TheObject = new MyObject();
TheListOfObjects = //some json deserialization result
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
TheObject.SomeProperty = SomeValue;
When I write TheObject.SomeProperty = SomeValue; am I:
modifying the item in the list and in which case I'm done or
modifying a new item and I must replace the original item in the list with the item I just modified.
Depends.
If the list of objects is a list of class instances, then TheObject variable will hold a value that is a reference. This reference will also still exist within the list. Modifications of the object at that reference will be visible in both. Important caveat: Writing over the reference contained in the variable (ie., variable reassignment) would not persist to the list, nor would writing over the reference in the list persist to the variable.
If the list of objects is a list of struct instances, then TheObject simply contains the value, and mutations of that value are not visible inside the list.
That depends on whether the MyObject is a class or a struct.
If it's a class, you're modifying the original object.
If it's a struct, you're modifying a copy.
Items in your list are held by reference, so you're modifying the same object - no need to try to copy it back into the list as it's already there.
You are modifying an item in the list. TheObject is a reference to an unique item in memory.
You can even create multiple lists, all lists will contain references to identical objects in memory.
There is something wrong with your code:
MyObject TheObject = new MyObject();
...
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
You are first creating a new instance of the object, the affecting to TheObject a new value.
The = new MyObject(); part of your code is useless. Same for = new List<MyObject>();
You are modifying the item in the list as the call returns a reference to the item in the list, not a copy of it. Also, the object you create with
MyObject TheObject = new MyObject();
is just thrown away, as you change the reference to the newly selected item. You could omit that line and just do:
MyObject theObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
I assume that MyObject is a class, and not a struct, because we are mutating it with the operation, and mutable structs are evil