好的,据我了解,不可变类型本质上是线程安全的,所以我已经在很多地方读过,我想我理解为什么会这样。如果一旦创建对象便无法修改实例的内部状态,则并发访问实例本身似乎没有问题。
因此,我可以创建以下List
:
class ImmutableList<T>: IEnumerable<T>
{
readonly List<T> innerList;
public ImmutableList(IEnumerable<T> collection)
{
this.innerList = new List<T>(collection);
}
public ImmutableList()
{
this.innerList = new List<T>();
}
public ImmutableList<T> Add(T item)
{
var list = new ImmutableList<T>(this.innerList);
list.innerList.Add(item);
return list;
}
public ImmutableList<T> Remove(T item)
{
var list = new ImmutableList<T>(this.innerList);
list.innerList.Remove(item);
return list;
} //and so on with relevant List methods...
public T this[int index]
{
get
{
return this.innerList[index];
}
}
public IEnumerator<T> GetEnumerator()
{
return innerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return ((System.Collections.IEnumerable)this.innerList).GetEnumerator();
}
}
所以问题是:这真的是不可变的类型吗?它真的是线程安全的吗?
显然,类型本身是不可变的,但是
T
绝对没有保证,因此您可能会遇到与通用类型直接相关的并发访问和线程问题。那是否意味着ImmutableList
应该被认为是可变的?class ImmutableList<T>: IEnumerable<T> where T: struct
是否应该是唯一真正被认为是不可变的类型?感谢您对此问题的任何投入。
更新:很多答案/评论都集中在我发布的
ImmutableList
的特定实现上,这可能不是一个很好的例子。但是问题的关键不是实现。我要问的问题是,考虑到不可变类型需要的所有内容,ImmutableList<MutableT>
是否真的是不可变类型。 最佳答案
通常是这样,是的。
简要总结一下:可变列表周围有一个写时复制包装器。向不可变列表中添加新成员不会使该列表发生变化。相反,它会制作基础可变列表的副本,将其添加到副本中,然后返回围绕该副本的包装器。
假设要包装的基础列表对象在读取时不会改变其内部状态,则您已满足“不可变”的原始定义,因此,是的。
我注意到这不是实现不可变列表的非常有效的方法。例如,使用不可变的平衡二叉树可能会做得更好。每次创建新列表时,草图在时间和内存上均为O(n);您可以毫不费力地将其改进为O(log n)。
前提是基础可变列表对于多个读取器是线程安全的,是的。
您可能对此感兴趣:
http://blogs.msdn.com/b/ericlippert/archive/2011/05/23/read-only-and-threadsafe-are-different.aspx
这是一个哲学问题,而不是技术问题。如果您有一个不可变的人名列表,并且列表从未更改,但是其中一个人死亡,那么名称列表是否为“可变”?我不会。
如果有关列表的任何问题始终具有相同的答案,则列表是不可变的。在我们的姓名列表中,“列表上有几个姓名?”是关于列表的问题。 “有多少人还活着?”不是关于 list 的问题,而是关于 list 所指的人的问题。这个问题的答案会随着时间而改变。第一个问题的答案不是。
我没有关注你。将T限制为结构如何改变什么? OK,T仅限于struct。我做了一个不变的结构:
struct S
{
public int[] MutableArray { get; private set; }
...
}
现在我制作一个
ImmutableList<S>
。是什么让我无法修改存储在S实例中的可变数组?仅仅因为列表是不可变的,而struct是不可变的,则不能使数组不可变。关于c# - 一成不变还是不一成不变?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9009627/