milheiros
milheiros

Reputation: 619

Preserve value of an object instance

I think this problem is a value/reference instantiate problem in Object Oriented languages like C#. But I'm newbie and I don't know how to turnaround.

I have a method with this piece of code:

    List<CSpropr> listActionpropr = CSpropr.searchList(actionCondition); // Get a list of all records of table PROPR for the 'actioncondition' specified
// For each record...
    foreach (CSpropr instance in listActionpropr)
       {
         instance.ValName = "John";
         instance.ValPhone = 323234232;
         instance.update(); // This make and UPDATE of the record in DB
       }

Later in the same method, I want to use the first version of listActionpropr, before the update. To make a sort of rollback. But when I iterate the listActionpropr variable I get the list of records with the changes in Name and Phone values. For example:

foreach (CSApropr instance1 in listActionpropr )
    {
      instance1.update();
    }

Is there an elegantly way to preserve the value without create a new search to other variable? Like this:

List<CSpropr> listActionpropr = CSpropr.searchList(actionCondition); // Get a list of all records of table PROPR for the 'actioncondition' specified
List<CSpropr> preservedList = CSpropr.searchList(actionCondition); // Get a list of all records of table PROPR for the 'actioncondition' specified
    // For each record...
        foreach (CSpropr instance in listActionpropr)
           {
             instance.ValName = "John";
             instance.ValPhone = 323234232;
             instance.update(); // This make and UPDATE of the record in DB
           }
....

foreach (CSApropr instance1 in preservedList )
        {
          instance1.update();
        }      

Upvotes: 0

Views: 1459

Answers (4)

sumeet more
sumeet more

Reputation: 1

Basically you want two identical lists but if you change one element of the list1 it should not affect the same element of list2 . You can do this in various ways: eg using serialization.

Following code will show my way:

Module Module1

Sub Main()

    Dim listone As New List(Of demo) 'first list
    Dim listwo As New List(Of demo)   ' second list
    Dim var1 As Integer
    Dim var2 As String
    Dim obj As New demo()           'first object created in list-1
    obj.id = 1
    obj.name = "sumi"
    listone.Add(obj)                'first object inserted in the list-1
    Dim obj1 As New demo()
    obj1.id = 3
    obj1.name = "more"
    listone.Add(obj1)               'Second object inserted in the list-1
    For Each w In listone
        Dim obj3 As New demo()
        var1 = w.id
        obj3.id = var1
        var2 = w.name
        obj3.name = var2
        listwo.Add(obj3)            'looping all objects of list-1 and adding them in list-2 .Hence making both lists identical

    Next
    For Each p In listone      'making change in the list-1 and this change should not be refelected in list-2
        If (p.id = 1) Then
            p.id = 5
        End If
    Next
    For Each z In listone
        Console.WriteLine(z.id)
        Console.WriteLine(z.name)

    Next
    For Each q In listwo
        Console.WriteLine(q.id)
        Console.WriteLine(q.name)
    Next
    Console.ReadLine()

End Sub
Class demo
    Public name As String
    Public id As Integer
End Class

End Module

Output:
5
sumi
3
more
1
sumi
3
more

Hence cloned list remains unaffected irrespective of changes in original list

Upvotes: 0

ANewGuyInTown
ANewGuyInTown

Reputation: 6437

What you are talking about is close to transactions in c# objects. There is no inherent support for object transactions in c#.

Microsoft did start a project on STM (Software Transactional Memory) to support the transaction features for .NET objects. However, the project has already been retired for various reasons.

So, all you can do now is have a separate object for original list. You could either DeepCopy the object with the some helper method as described in other answer or implement IClonable interface for you object, which does the deep copy for you. An example would be :

public class Person : ICloneable
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public Address PersonAddress { get; set; }

    public object Clone()
    {
        Person newPerson = (Person)this.MemberwiseClone();
        newPerson.PersonAddress = (Address)this.PersonAddress.Clone();

        return newPerson;
    }
}

The Address class uses MemberwiseClone to make a copy of itself.

public class Address : ICloneable
{
    public int HouseNumber { get; set; }
    public string StreetName { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

Cloning a Person:

Person herClone = (Person)emilyBronte.Clone();

The example is taken from one of the excellent blogs in internet for c#

Of course, when I meant object, it's applicable to List<objects> as well.

Upvotes: 1

Igoris
Igoris

Reputation: 1650

I would use DeepClone in this case with serialization as per this answer : https://stackoverflow.com/a/519512/841467

My fast implementation in LinqPad was :

void Main()
{
    List<CSpropr> listActionpropr = CSpropr.searchList("act"); // Get a list of all records of table PROPR for the 'actioncondition' specified
    List<CSpropr> preservedList = listActionpropr.DeepCopy(); // Get a list of all records of table PROPR for the 'actioncondition' specified
    // For each record...
    foreach (CSpropr instance in listActionpropr)
    {
        instance.ValName = "John";
        instance.ValPhone = 323234232;
        instance.update(); // This make and UPDATE of the record in DB
    }

    foreach (CSpropr instance1 in preservedList )
    {
        instance1.update();
    }
}

// Define other methods and classes here
[Serializable]
public class CSpropr {
    public string ValName {get;set;}
    public int ValPhone {get;set;}

    public void update() {
        ValName.Dump();
        ValPhone.Dump();
    }

    public static List<CSpropr> searchList(string act) {
        return new List<CSpropr> { new CSpropr {ValName = "First", ValPhone = 4444} , new CSpropr {ValName = "First", ValPhone = 4444 }};   
    }
}

public static class GenericCopier
{
    public static T DeepCopy<T>(this T original) where T : class
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(memoryStream, original);
            memoryStream.Seek(0, SeekOrigin.Begin);
            return (T)binaryFormatter.Deserialize(memoryStream);
        }
    }
}

result is :

John 323234232 John 323234232 First 4444 First 4444

Upvotes: 1

Orkun Bekar
Orkun Bekar

Reputation: 1441

You can store your first list object like that:

List<CSpropr> StoreFirstListInTemp(List<CSpropr> listActionpropr)
{
  List<CSpropr> temp = new List<CSpropr>();
  temp.AddRange(listActionpropr);
  return temp;
}

Upvotes: -1

Related Questions