My goal here is to retrieve a List from a class instance and then modify the objects within that list, however I do not know how the objects will be affected and need some valuable knowledge.
Let's say we have two cases:
Create a new List which gets the list from the class instance:
List<SomeType> ItemsList {get { return classInstance.ItemsList;} set {...
Create a new List of wrappers, each item in the list contains the original object with some additional properties:
List<SomeType> itemsList = classInstance.ItemsList;
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x, IsSelected = ...
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
I will be using multiple ObservableCollections in multiple DataGrids, I have used Lists in this example simplify the situation but I'm sure the result would be the same.
Edit:
I realize the Title does not describe my problem well, I encourage anyone to help me improve it.
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
Yes, unless you create a copy SomeType and add the copy to the new collection.
The following creates a new Wrapper objects for each SomeType object...
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x } );
...but each Wrapper object still has a reference (though the Item property) to the same SomeType object that's in classInstance.ItemsList.
When the properties of SomeType (mutable reference type) instances are changed via Wrapper then the objects in the original list change, because they are the same objects.
When the list holding Wrapper objects changes (you move, add or remove objects) the the original list is not affected.
When original list is changed (you move, add or remove objects) the list containing Wrappers is not affected.
To synchronise the collections, you should use ObservableCollection for original list and implement collection (probably also ObservableCollection-derived) for Wrappers that auto-updates itself when source collection changes.
Related
I have defined a list of objects as List<NewLayerCounterMethod> NewLayer = new List<NewLayerCounterMethod>(); where each object within the class NewLayerCounterMethod has four properties such as: VehicleType, VehicleCounter,Counter,Updating.
The number of objects NewLayer is 10 and I want to copy NewLayer[7] into NewLayer[5] such that if NewLayer[7] is changed, NewLayer[5] will not be changed.
Please note that I do not want to make a new object while I want to replace the properties of one object with those of another object which makes it somehow different from other questions on Stackoverflow and I think it is not a duplication.
You need to clone the object, as otherwise you would just store the reference and in both fields and change them both. See this answers:
Creating a copy of an object in C#
How do you do a deep copy of an object in .NET (C# specifically)?
In that case you need to add a function to your NewLayerCounterMethod class, in which you copy all the properties of the other class to the new one. It would look somewhat like that then:
public void TakeProperties(NewLayerCounterMethod otherObject)
{
propA = otherObject.propA;
propB = otherObject.propB;
//And so on for all properties left
}
You could add guards so that you only update the properties if the new value is different to the old one, but I suggest to add those guards directly to the properties.
The above method is than called like that:
NewLayer[5].TakeProperties(NewLayer[7]);
I'm creating two objects and assign them with a data from IsolatedStorage.
But when I change one object the second one changes too. ( I think the problem may be the pointers are the same, but I can't solve it. )
private ArrayOfClsSimpleData lstUsers;
private ArrayOfClsSimpleData tmpLstUsers;
in class' globals
tmpLstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("users");
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("users");
The first status of the arrays:
Debug.Write(lstUsers.Count)
Output: 2
Debug.Write(tmpLstUsers.Count)
Output: 2
The counts are the same as expected. But, after I add an item to one list, the other list gets updated too and the counts are still same.
lstUsers.Add(new ArrayOfClsSimpleData());
Debug.Write(lstUsers.Count)
Output: 3
Debug.Write(tmpLstUsers.Count)
Output: 3
EDIT : IsolatedStorageHelper class is something to help to get objects, save object etc. that I do use for simplifying things, so just think it as getting objects from IsolatedStorage.
it is implemented like this:
public static T GetObject<T>(string key)
{
if (IsolatedStorageSettings.ApplicationSettings.Contains(key))
{
return (T)IsolatedStorageSettings.ApplicationSettings[key]; // return the object
}
return default(T); // if key doesn't exists , return default object
}
So it just gets it from IsolatedStorage.
If you don't know isolated storage you can see it from here
So, how can I fix the code so that I can change one without changing the other?
So, basically lstUsers and tmpLstUsers are references to the same object. All you have to do is to create a new one and copy content from the original. If you need a quick solution, then you can do it like this (code below). I just guess that ArrayOfClsSimpleData is some kind of array.
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("myKey");
tmpLstUsers = new ArrayOfClsSimpleData();
foreach (object user in lstUsers) // I don't know the type of objects in ArrayOfClsSimpleData, so I wrote 'object', but you should use the actual type
tmpLstUsers.Add(user);
The problem is that IsolatedStorage is just returning two pointers to the same data. So unless you copy the data, all changes will ultimately be to the same underlying data.
Think of it as two copies of your home address. Anything you change on your home affects all copies of your address since it is just an address and not the home itself.
What you will want to do is clone your object. Built in collections have clone or copy methods built in to do shallow copies, or if you built something yourself you will need to implement it yourself
The easiest way is to implement the IClonable interface and to use the clone method to achieve your copying.
https://msdn.microsoft.com/en-us/library/System.ICloneable.aspx
This basically involves going through and calling member wise clone for each complex object (which will copy all value types for you)
https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
I don't think cloning is necessary. Just create a new list instead of operating on the same instance. You can do that by calling ToList() on the returned instance:
lstUsers = IsolatedStorageHelper.GetObject<ArrayOfClsSimpleData>("myKey").ToList();
Can't you use the Clone() method of IClonable while fetching the object? looks like both list objects are getting same reference objects.
I want a copy of an ObservableCollection by filtering it with some condition. Please help me.
I treid the following code:
ObservableCollection<YourEntity> clonedCollection = new ObservableCollection<YourEntity>(clonedList);
This is ok, but need copy with condition (new object filtered from the old one). need to copy some particular data from clonedList
Use a linq query to filer the elements in the source collection.
A .Where() query does it pretty good. You can use .Select() or any other query too.
ObservableCollection<YourEntity> cloned = new ObservableCollection<YourEntity>(source.Where(e => e.IsSomeConditionFulfilled()));
Note that you do not clone the objects passing an IEnumerable to the constructor of the ObservableCollection - both collections cloned and source will reference the same objects. That means, if you change some YourEntity instance properties via the source collection (e. g. source.First().SomeProperty = SomeValue), and this object is also contained in the cloned collection (e. g. cloned.First() == source.First()), then those changes will be reflected there.
I'm trying to create an ArrayList of objects in C#. What I've tried so far is:
class POObject
{
public List<string> staticCustInfo;
public List<List<string>> itemCollection;
public int testInt;
}
POObject myObject = new POObject();
List<POObject> BatchList = new List<POObject>();
This is fine, except when I try to add an object to this list using:
BatchList.Add(item);
It gives me errors saying it can't find a corresponding method to add to the list. Any ideas? Thanks for the help.
What are you trying to store in your list? You declare a BatchList as containing POObjects, but then you're trying to add item, which is of what type? If you're adding things to this list that are not POObjects, you can declare it as either a non-generic list:
List BatchList = new List();
or as a generic list of objects:
List<object> BatchList = new List<object>();
But I suspect the real problem may be that you're trying to add the wrong type of item to your collection. Can you show us how you get your item variable?
If you declare that BatchList is of type List<POObject>, then that means the List can only contain objects of type POObject. That's what the type parameter is for. You cannot add strings, ints, or any other arbitrary objects to this list, only POObjects (and descendents of POObject).
If you take a look at the intellisense, you will see that Add's signature is this:
void Add(POObject item)
If you really want a list that contains arbitrary items, then use an ArrayList, which is not a generic type and can accept any type of object. However since C# is such a strongly typed language, wanting arbitrary lists like this is usually a code smell.
why does
List<Object> objectList; = some objects
List<Object> getList()
{
return objectList; //or return new List<Object>(objectList);
}
return a list with all items referenced to the original list's items?
Thanks.
In the first case you just return a reference to the list.
In the second case (new List<Object>(list)) the objects are not copied: only the references are copied! You have to clone each item in the collection to return a deep copy of the list.
EDIT:
Iterate through your whole list and create a copy of each of your objects and put them into a new list.
See this for creating deep copies of custom objects. I would suggest not to use the interface ICloneable. Make some research to learn why. :)
It is a reference
You're returning a reference to ObjectList. : )
AboutTheConstructor:
From MSDN: List<(Of <(T>)>)(IEnumerable<(Of <(T>)>)) Initializes a new instance of the List<(Of <(T>)>) class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
Basically, because List<> and Object are reference types. If you read up on reference/value types in C# here: http://msdn.microsoft.com/en-us/library/3ewxz6et(v=VS.100).aspx it should make sense to you.
if you are using a custom object, Implement the ICloneable interface on the object.
Then, when you are returning your list, clone the objects into a new list. When you pass your old list into the constructor of your new list, you are passing references to all the objects in the original list, unless they are value type (string, int, etc)