Home > Software engineering >  C# method returns list by reference instead of by value
C# method returns list by reference instead of by value

Time:09-23

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();
}
  • Related