Is there an easy way to basically just get a copy of the data instead of a reference using this method? I tried .ToArray().Where() but that still seems to pass a reference.
Example:
static void Main(string[] args)
{
List<ob> t = new List<ob>();
t.Add(new ob() { name = "hello" });
t.Add(new ob() { name = "test" });
ob item = t.Where(c => c.name == "hello").First();
// Changing the name of the item changes the original item in the list<>
item.name = "burp";
foreach (ob i in t)
{
Console.WriteLine(i.name);
}
Console.ReadLine();
}
public class ob
{
public string name;
}
A much easier way to go is to simply serialize your data to json and then back again. It takes a small performance hit but it is safer as it less error prone and you don't need to modify all your classes.
simply do:
As
ob
is a class, it is a reference type and therefore any instance ofob
, when assigned to a different variable (as is happening within the lineob item = t.Where(c => c.name == "hello").First();
) will automatically copy the reference to the original instance, and not copy the actual instance itself. This is a general .NET topic regarding object copying and is separate from LINQ/Lambda,In order to achieve what you want, you'll need to either create a Shallow Copy or a Deep Copy of the resulting instance from your LINQ projection.
For your
ob
class, a Shallow Copy would suffice (ShallowCopy generally copies as little as possible whereas DeepCopy copies everything - A good reference for the differences can be found here).To perform a ShallowCopy of an object, you can use a simply
MemberwiseClone
which is a built-in method of .NET object type, inherited by all objects.For something more substantial, you'll have to implement your own DeepCopy function, but that can be relatively simple. Something similar to these implementations as specified here and here.
You need to create a copy of your
ob
yourself - it's not something LINQ provides.You could define a
Clone
method based on the existingprotected MemberwiseClone
method:Then: