不变的还是不变的? [英] Immutable or not immutable?

查看:135
本文介绍了不变的还是不变的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,根据我的理解,不可变的类型本质上是线程安全的,所以我已经在各个地方读过,我想我明白为什么会这样。如果实例的内部状态在创建对象后无法修改,似乎并发访问实例本身就没有问题。



因此,我可以创建以下列表

  class ImmutableList< T>:IEnumerable< T& ; 
{
只读列表< T> innerList;

public ImmutableList(IEnumerable< T>集合)
{
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);
返回列表;
}

public ImmutableList< T>删除(T项)
{
var list = new ImmutableList< T>(this.innerList);
list.innerList.Remove(item);
返回列表;
} //等等与相关的列表方法...

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>其中T:struct 是唯一真正被认为是不可变的类型



感谢您对此问题的任何意见。 / p>

更新:很多答案/评论集中在 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


显然,类型本身是不可变的,但是绝对没有保证T是,因此你可以具有并发访问和线程与通用类型直接相关的问题。这意味着 ImmutableList< T> 应该被认为是可变的?


这是一个哲学问题,而不是技术问题。如果你有一个不可变的人名单,名单从来没有改变,但其中一个人死亡,名字叫可变?我不会想



如果关于列表的任何问题总是有相同的答案,列表是不可变的。在我们的名单中,名单上有多少名字?是一个关于列表的问题。 有多少人还活着?这不是一个关于这个名单的问题,这是一个关于名单所提到的人的问题。这个问题的答案随时间而变化;第一个问题的答案不是。


应该是class ImmutableList< T>:IEnumerable< T>其中T:struct 是唯一被认为是不可变的类型?


我没有关注你。如何限制T成为一个结构体改变任何东西?好的,T只限于struct。我做了一个不可变的结构:

  struct S 
{
public int [] MutableArray {get;私人集合}
...
}

现在我做一个 ImmutableList< S> 。什么阻止我修改存储在S的实例中的可变数组?只是因为列表是不可变的,并且结构是不可变的,不会使数组不可变。


Ok, as I understand it, immutable types are inherently thread safe or so I've read in various places and I think I understand why it is so. If the inner state of an instance can not be modified once the object is created there seems to be no problems with concurrent access to the instance itself.

Therefore, I could create the following 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();
    }
}

So the question is: Is this really an immutable type? Is it really thread safe?

Obviously the type itself is immutable but there is absolutely no garantee that T is and therefore you could have concurrent access and threading issues related directly with the generic type. Would that mean that ImmutableList should be considered mutable?.

Should class ImmutableList<T>: IEnumerable<T> where T: struct be the only type truly considered immutable?

Thanks for any input on this issue.

UPDATE: A lot of answers/comments are concentrating on the particular implementation of ImmutableList I've posted which is probably not a very good example. But the issue of the question is not the implementation. The question I'm asking is if ImmutableList<MutableT> is really an immutable type considering everything that an immutable type entails.

解决方案

If the inner state of an instance can not be modified once the object is created there seems to be no problems with concurrent access to the instance itself.

That is generally the case, yes.

Is this really an immutable type?

To briefly sum up: you have a copy-on-write wrapper around a mutable list. Adding a new member to an immutable list does not mutate the list; instead it makes a copy of the underlying mutable list, adds to the copy, and returns a wrapper around the copy.

Provided that the underlying list object you are wrapping does not mutate its internal state when it is read from, you have met your original definition of "immutable", so, yes.

I note that this is not a very efficient way to implement an immutable list. You'd likely do better with an immutable balanced binary tree, for example. Your sketch is O(n) in both time and memory every time you make a new list; you can improve that to O(log n) without too much difficulty.

Is it really thread safe?

Provided that the underlying mutable list is threadsafe for multiple readers, yes.

This might be of interest to you:

http://blogs.msdn.com/b/ericlippert/archive/2011/05/23/read-only-and-threadsafe-are-different.aspx

Obviously the type itself is immutable but there is absolutely no garantee that T is and therefore you could have concurrent access and threading issues related directly with the generic type. Would that mean that ImmutableList<T> should be considered mutable?.

That's a philosophical question, not a technical one. If you have an immutable list of people's names, and the list never changes, but one of the people dies, was the list of names "mutable"? I would think not.

A list is immutable if any question about the list always has the same answer. In our list of people's names, "how many names are on the list?" is a question about the list. "How many of those people are alive?" is not a question about the list, it is a question about the people referred to by the list. The answer to that question changes over time; the answer to the first question does not.

Should class ImmutableList<T>: IEnumerable<T> where T: struct be the only type truely considered immutable?

I'm not following you. How does restricting T to be a struct change anything? OK, T is restricted to struct. I make an immutable struct:

struct S
{
    public int[] MutableArray { get; private set; }
    ...
}

And now I make an ImmutableList<S>. What stops me from modifying the mutable array stored in instances of S? Just because the list is immutable and the struct is immutable doesn't make the array immutable.

这篇关于不变的还是不变的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆