How to get a copy of data instead of a reference u

2019-04-25 12:56发布

问题:

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;
}

回答1:

You need to create a copy of your ob yourself - it's not something LINQ provides.



回答2:

You could define a Clone method based on the existing protected MemberwiseClone method:

public class Item
{
    public Item Clone()
    {
        return (Item)this.MemberwiseClone();
    }
}

Then:

ob item = t.Where(c => c.name == "hello").First().Clone();


回答3:

As ob is a class, it is a reference type and therefore any instance of ob, when assigned to a different variable (as is happening within the line ob 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.



回答4:

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:

var json = JsonConvert.SerializeObject(myObject)
var clone = JsonConvert.DeserializeObject<T>(json)


标签: c# linq lambda