公共财产&不变性

时间:2011-08-28 13:40:29

标签: .net immutability

每当属性Test被攻击时,是否有更好的方法可以确保以下Array类的不可变性而无需返回数组的新深层副本(请假设DeepCopy()是一个扩展方法,它创建了一个新的数组深层副本)?

public class Test
{
    private SomeObject[] _array;

    public SomeObject[] Array
    {
        get { return (_array.DeepCopy();) }
    }

    public Test(SomeObject[] array) 
    {
        _array = array.DeepCopy();
    }
}

在每次访问属性时,它都会在初始化时进行深层复制,而另一个则进行深入复制。有没有更好的方法来实现不变性?

3 个答案:

答案 0 :(得分:2)

.NET 1 没有“深度不可变”的集合,使成员元素不可变。例如。 ReadonlyCollection<T>会阻止添加/删除元素,但不会复制单个元素,因此可能仍会更改其属性。

因此,如果它们本身不可变,则必须复制构成该集合的元素。如果元素是不可变的,那么在集合周围放置一个浅不可变的包装器(如ReadonlyCollection<T>)就足够了。


1 考虑BCL。像F#运行时这样的扩展是另一回事。

答案 1 :(得分:1)

System.Collections.Generic.List&LT;&GT;实现AsReadOnly函数,并且有一个System.Collections.ReadOnlyCollectionBase类,您可以从该类继承表示只读元素集合的类。但是,虽然那些行为像数组,但它们不是实际的数组。实际数组总是允许更改元素。因此,我能想到的唯一选择是正在制作副本,或者将每个级别的对象包装在只读包装中。

另请参阅:Read-only array in .NET

答案 2 :(得分:0)

Properties should not return arrays。这是您运行FxCop时将收到的消息之一。 Microsoft页面建议的一个解决方案是返回ReadOnlyCollection&lt; T&gt;正如@BlueMonkMN建议的那样。您还可以使用IEnumerable&lt; T&gt; (假设您可以信任消费者不要投出结果)。