I have a class with a static list as shown below:
public class Context
{
private static readonly List<Definition> definitions;
static Context()
{
definitions = LoadXML("path-to-xml-file.xml"));
}
public static List<Definition> GetDefinitions()
{
return definitions;
}
}
My problem is making calls to GetDefinitions()
seems to return the list by reference instead of by value, because when I do this elsewhere in my code:
var defs = Context.GetDefinitions().ToList();
defs.ForEach(a =>
{
a.Name = a.Alias ?? a.Name;
});
all subsequent calls to Context.GetDefinitions()
will return the modified list - not the original one, hence my conclusion that defs
is not a value but a reference to the definitions
list.
I tried adding the .ToList()
in an attempt to decouple the reference but still I get the same result.
I am also open to a workaround, which allows me to use .Select()
instead of .ForEach()
in my sample code.
CodePudding user response:
The problem is that the list does not store the items itself, but rather references to the items. Even if you create a new list (e.g. with ToList()
), the referenced items stay the same.
In order to fix this, you need to clone the items in the list so that you have a independent copy of the data. You can implement ICloneable
on the items and use return the list like this:
public static List<Definition> GetDefinitions()
{
return definitions.Select(x => (Definition)x.Clone()).ToList();
}
This way you create a new list that contains the cloned items. However, cloning an item is a tedious task if you need to clone a deeply nested class structure. For a flat structure, using MemberwiseClone
is an easy way.
CodePudding user response:
You need to return new List in
public static List<Definition> GetDefinitions()
{
return definitions;
}
Change code to
public static List<Definition> GetDefinitions()
{
return definitions.ToList();
}