How do I change my new list without changing the original list?

后端 未结 11 1866
萌比男神i
萌比男神i 2020-12-03 08:30

I have a list that gets filled in with some data from an operation and I am storing it in the memory cache. Now I want another list which contains some sub data from the li

相关标签:
11条回答
  • 2020-12-03 08:50

    Build a new list first and operate on that, because List is a reference type, i.e. when you pass it in a function, you do not just pass the value but the actual object itself.

    If you just assign target to mainList, both variables point to the same object, so you need to create a new List:

    List<Item> target = new List<Item>(mainList);
    

    void List<Item> SomeOperationFunction() makes no sense, because either you return nothing (void) or you return a List<T>. So either remove the return statement from your method or return a new List<Item>. In the latter case, I would rewrite this as:

    List<Item> target = SomeOperationFunction(mainList);
    
    List<Item> SomeOperationFunction(List<Item> target)
    {
        var newList = new List<Item>(target);
        newList.RemoveAt(3);
        return newList;
    }
    
    0 讨论(0)
  • 2020-12-03 08:50

    Instead of assigning mainList to target, I would do: target.AddRange(mainList);

    Then you will have a copy of the items instead of a reference to the list.

    0 讨论(0)
  • 2020-12-03 08:53

    You need to make a copy of the list so that changes to the copy won't affect the original. The easiest way to do that is to use the ToList extension method in System.Linq.

    var newList = SomeOperationFunction(target.ToList());
    
    0 讨论(0)
  • 2020-12-03 08:54

    You need to clone your list in your method, because List<T> is a class, so it's reference-type and is passed by reference.

    For example:

    List<Item> SomeOperationFunction(List<Item> target)
    {
      List<Item> tmp = target.ToList();
      tmp.RemoveAt(3);
      return tmp;
    }
    

    Or

    List<Item> SomeOperationFunction(List<Item> target)
    {
      List<Item> tmp = new List<Item>(target);
      tmp.RemoveAt(3);
      return tmp;
    }
    

    or

    List<Item> SomeOperationFunction(List<Item> target)
    {
      List<Item> tmp = new List<Item>();
      tmp.AddRange(target);
      tmp.RemoveAt(3);
      return tmp;
    }
    
    0 讨论(0)
  • 2020-12-03 09:04

    Since a List is a reference type, what is passed to the function is a reference to the original list.

    See this MSDN article for more information about how parameters are passed in C#.

    In order to achieve what you want, you should create a copy of the list in SomeOperationFunction and return this instead. A simple example:

    void List<Item> SomeOperationFunction(List<Item> target)
    {
      var newList = new List<Item>(target);
      newList.RemoveAt(3);
      return newList; // return copy of list
    }
    

    As pointed out by Olivier Jacot-Descombes in the comments to another answer, it is important to bear in mind that

    [...] the list still holds references to the same items if the items are of a reference type. So changes to the items themselves will still affect the items in both lists.

    0 讨论(0)
  • 2020-12-03 09:04

    You'll need to make a copy of the list since in your original code what you're doing is just passing around, as you correctly suspected, a reference (someone would call it a pointer).

    You could either call the constructor on the new list, passing the original list as parameter:

    List<Item> SomeOperationFunction(List<Item> target)
    {
        List<Item> result = new List<Item>(target);
        result.removeat(3);
        return result;
    }
    

    Or create a MemberWiseClone:

    List<Item> SomeOperationFunction(List<Item> target)
    {
        List<Item> result = target.MemberWiseClone();
        result.removeat(3);
        return result;
    }
    

    Also, you are not storing the return of SomeOperationFunction anywhere, so you might want to revise that part as well (you declared the method as void, which should not return anything, but inside it you're returning an object). You should call the method this way:

    List<Item> target = SomeOperationFunction(mainList);
    

    Note: the elements of the list will not be copied (only their reference is copied), so modifying the internal state of the elements will affect both lists.

    0 讨论(0)
提交回复
热议问题