Reputation: 619
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
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
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
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
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