1

help me please to use the function "RemoveAll" or maybe there should be another implementation. I have an object (services) which contains a list with items. I make another object (anotherService ) which is equal with the first.

I should remove from second object (anotherService) items which have mainService == false.

I use the "RemoveAll" function, but after this action is made, from the object (services) items which are mainService = false are also removed. I need to have the first object completed how it was before removing.

var services = DictionaryObject.GetDictionaryValidatedByDate<ServiceInfo>(DictionaryType.REF_SERVICE, DateTime.Now);

var anotherService = services;

anotherService.RemoveAll(p =>                
    {                   
        if (p.Model.mainService == false)
        {
           return true;
        }
        return false;
    });

Thank you all.

mihai
  • 2,746
  • 3
  • 35
  • 56
  • 1
    as a side-note: You can also simplify your check logic to anotherService.RemoveAll(p => !p.Model.mainService); – iCollect.it Ltd Oct 03 '11 at 14:06
  • 1
    if you could tell use the types of `services` rather than just `var` it might help. – Sam Holder Oct 03 '11 at 14:17
  • i tried to create the `anotherService` using the type of `services`, but, it was impossible, because the type of `services` results after `GetDictionaryValidatedByDate` method runs, and is a private type from WebServices: `RefDictionary`, and is not accessible. – mihai Oct 03 '11 at 15:49

3 Answers3

2

The line:

var anotherService = services;

simply defines a new variable and assigns the existing value (almost certainly a class reference) to that variable; no new object is created. Any member-access on a reference is going to go to the same actual object, no matter which variable you use (there is only one object).

To do what you need, you would need to create a shallow or deep clone (depending on what exactly you want to happen).

A shallow clone is pretty easy to do by manually adding a Clone() method or similar (maybe ICloneable) which copies the properties (noting that in the case of lists, a new list with the same data is usually created). A deep clone is trickier - a common cheat there is to serialize and deserialize the item.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

The Serialization approach can be found here in this answer :

For reference I have posted it here.

public static T DeepClone<T>(T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}
Community
  • 1
  • 1
Robin Maben
  • 22,194
  • 16
  • 64
  • 99
1

Your problem is that you are changing the same object, just through a different reference. you need to make sure that you removes items from a different object, which contains copies of the same information. There are a few ways you could do this. The simplest is to just create 2 objects:

var services = DictionaryObject.GetDictionaryValidatedByDate<ServiceInfo>(DictionaryType.REF_SERVICE, DateTime.Now);

var anotherService =  DictionaryObject.GetDictionaryValidatedByDate<ServiceInfo>(DictionaryType.REF_SERVICE, DateTime.Now);;

anotherService.RemoveAll(p =>                
    {                   
        if (p.Model.mainService == false || p.Model.mainService == true)
        {
           return true;
        }
        return false;
    });

or you could copy/clone your object something like:

var anotherService = services.Copy(); //or maybe use a copy constructor here instead:
//  var anotherService = new ServiceInfo(sevices);
anotherService.RemoveAll(p =>                
{                   
    if (p.Model.mainService == false || p.Model.mainService == true)
    {
       return true;
    }
    return false;
});

When you implement the Copy() method or the constructor which takes the object to copy you need to make sure that you create copies of dictionaries and do not just use references to the same dictionary.

if your object being returned is just an IDictionary<K,V> (its not clear from the code provided) you may be able to do this:

var anotherService = new Dictionary<KeyType,ValueType>(services)
anotherService.RemoveAll(p =>                
{                   
    if (p.Model.mainService == false || p.Model.mainService == true)
    {
       return true;
    }
    return false;
});
Sam Holder
  • 32,535
  • 13
  • 101
  • 181
  • at 'services' object I have not available the 'Copy()' or 'Clone()' – mihai Oct 03 '11 at 14:09
  • 1
    no, obviously you have to implement this method yourself, the point being that you in some way need to create a copy of the object, not use the same reference. – Sam Holder Oct 03 '11 at 14:16
  • i think can obtain the `anotherService` running again the method `DictionaryObject.GetDictionaryValidatedByDate(DictionaryType.REF_SERVICE, DateTime.Now);`... but, this way needs more resources, and i wanted to do this more efficiently (wasntme) – mihai Oct 03 '11 at 15:52