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.
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.