不可变列表不添加数据

时间:2014-09-13 14:26:18

标签: c# .net multithreading

我使用的是ImmutableList,如下所示:

  • 使用Nuget引用该包,以下是使用代码:

    using System.Collections.Immutable;
    
    private ImmutableList<Data> immutableList = ImmutableList.Create<Data>();
    
    // Write Action
    
    Action writeAction = (() =>
            {
                Data writeData = new Data();
    
                // Fill Data type with valid values
    
                immutableList.Add(writeData);    
    
            });
    

上面的代码不会将任何数据添加到Immutable列表中。它仍然是空的,我无法弄清楚所有数据是否有效的原因。类似的代码用于填充其他数据结构,如ConcurrentQueue和ConcurrentBag,它工作正常。

我在使用不可变列表时遗漏了什么,是否需要更正? 请注意这是一个多线程操作,但这不是问题,因为这个数据结构是线程安全的。

4 个答案:

答案 0 :(得分:12)

由于名称建议列表是不可变的,即您无法将该项目添加到原始列表中。在MSDN链接的备注部分:

  

当您从不可变列表副本中添加或删除项目时   原始列表是使用添加或删除的项目,以及   原始列表不变。


同样来自here,添加方法文档:

  

它返回一个添加了对象的新的不可变列表,如果是,则返回当前列表   已包含指定的对象。

添加将获得添加了项目的新列表引用(原始列表将保持不变):

immutableList = immutableList.Add(writeData);

答案 1 :(得分:2)

不可变列表是不会更改的列表。以下是MSDN对其含义的描述:

  

当您从不可变列表中添加或删除项目时,将使用添加或删除的项目创建原始列表的副本,并且原始列表不会更改。

这意味着每次执行Add这样的操作时,原始列表都不会更改,但会返回带有添加元素的新列表。这意味着您需要使用这样的代码来获得正确的列表:

immutableList = immutableList.Add(writeData); 

这让我觉得你在错误的情况下使用它。

答案 2 :(得分:0)

=

这对我来说很有效。

答案 3 :(得分:-1)

答案已经说明不可变列表确实是不可变的,例如,当您添加项目时,您必须将添加操作中的新不可变列表指定给相同的变量。

更容易使用的一种可能性是使用功能容器类包装不可变列表,如下面的代码,可以将其粘贴到 Linqpad 5 中(确保按 F4 将 Nuget 引用添加到 System.Collections.Immutable 并选择来自该程序集的命名空间)。

void Main()
{
    var numbersInImmutableList = new ImmutableWrappedList<int>();
    numbersInImmutableList.AddRange(new[] { 3, 1, 4, 1, 5, 9, 2 }); 
    numbersInImmutableList.AddRange(new[]{ 2, 7, 1, 8, 2, 1, 8 });
    numbersInImmutableList.RemoveAt(2);
    numbersInImmutableList.Dump();  
}

public class ImmutableWrappedList<T>  {
    public ImmutableList<T> _internalList {get; private set; }
    
    public ImmutableWrappedList()
    {
        _internalList = ImmutableList.Create<T>();  
    }
    
    public void Clear() => _internalList.Clear();   
    public void AddRange(IEnumerable<T> itemsToAdd) => _internalList = _internalList.AddRange(itemsToAdd);
    public void Add(T itemToAdd) => _internalList = _internalList.Add(itemToAdd);
    public void Remove(T itemToAdd) => _internalList = _internalList.Remove(itemToAdd);
    public void RemoveAt(int index) => _internalList = _internalList.RemoveAt(index);
    public void Insert(T itemToAdd, int position) => _internalList = _internalList.Insert(position, itemToAdd);
}

Immutable Array wrapping class demo that can be run inside Linqpad 5