标签: immutable-collections

返回ImmutableMap或Map更好吗?

假设我正在编写一个应该返回Map的方法.例如:

public Map<String, Integer> foo() {
  return new HashMap<String, Integer>();
}
Run Code Online (Sandbox Code Playgroud)

在考虑了一段时间之后,我决定在创建Map之后没有理由修改它.因此,我想返回一个ImmutableMap.

public Map<String, Integer> foo() {
  return ImmutableMap.of();
}
Run Code Online (Sandbox Code Playgroud)

我应该将返回类型保留为通用Map,还是应该指定我返回一个ImmutableMap?

从一个方面来说,这就是为什么创建接口的原因; 隐藏实现细节.
另一方面,如果我将这样离开,其他开发人员可能会错过这个对象是不可变的这一事实.因此,我不会实现不可变对象的主要目标; 通过最小化可以更改的对象的数量来使代码更清晰.甚至最糟糕的是,过了一段时间,有人可能会尝试更改此对象,这将导致运行时错误(编译器不会对此发出警告).

java design-patterns immutable-collections

88
推荐指数
7
解决办法
1万
查看次数

为什么在ReadOnlyCollection上使用ImmutableList?

.NET 4.5有一个新的命名空间System.Collections.Immutable

此包提供了线程安全的集合,并保证永远不会更改其内容,也称为不可变集合.

我糊涂了.是不是ReadOnlyCollection类已经解决了线程安全问题?为什么要使用ImmutableList呢?


我知道还有一个IReadOnlyList 接口.这并不能隐式解决线程安全问题,因为其他线程可能会通过另一个接口编辑该对象.

.net c# immutable-collections

51
推荐指数
4
解决办法
2万
查看次数

ImmutableArray <T>和ImmutableList <T>之间的区别

什么是ImmutableArray<T>和之间的区别ImmutableList<T>,哪个最好使用每个?

.net c# immutable-collections

28
推荐指数
4
解决办法
3459
查看次数

我是否必须包含所有System.Collections.Immutable依赖项?

我只是从(一个较旧的)Microsoft.Bcl.ImmutableNuGet包切换到System.Collections.Immutable并且很惊讶在我的项目中找到所有这些新的包依赖项:

System.Collections
System.Diagnostics.Debug
System.Globalization
System.Linq
System.Resources.ResourceManager
System.Runtime
System.Runtime.Extensions
System.Threading
Run Code Online (Sandbox Code Playgroud)

它们被列为NuGet包的依赖项,因此它们有权在那里,但它们显然也已经安装在我的PC和我的目标环境(Azure btw)上,因为它们随框架一起提供.

我已经在我的项目中有大量的软件包,并且如果可能的话,我希望避免由这8个软件包引起的额外开销(并且不会在脚下拍摄自己).

删除这些依赖项是否安全?
我现在是否必须在整个项目中使用这些软件包,因为它们可能与已安装的版本不同,我的项目的某些部分现在可能使用了错误的软件包?(由于某些DLL连接疯狂?)

编辑:只是为了完整性,因为之前有一个评论:依赖项是实际的包(不是名称空间),必须下载,我的目标是使用.NET 4.6进行编译,在VS2015中工作.虽然有些东西已经过时且包装不需要正常加载,但这是完全可能的吗?

.net c# nuget nuget-package immutable-collections

24
推荐指数
1
解决办法
7279
查看次数

ReadOnlyDictionary和ImmutableDictionary之间有什么区别?

在C#中,这两个容器之间的关键区别(在功能或用例方面)是什么?似乎没有任何信息可以在Google上比较这些信息.

System.Collections.ObjectModel.ReadOnlyDictionary System.Collections.Immutable.ImmutableDictionary

我知道ImmutableDictionary是线程安全的.ReadOnlyDictionary也是如此吗?

.net c# immutable-collections

21
推荐指数
2
解决办法
3017
查看次数

跨API传递不可变集合的最佳模式是什么

在不可变性之前,IEnumerable是许多API中的首选接口,因为它具有API对传递对象的实际类型不敏感的优点.

public void DoSomeEnumerationsWithACollection(IEnumerable<Thing> collectionOfThings)
{ 
   foreach (var thing in collectionOfThings) doSomethingWith(thing);
   foreach (var thing in collectionOfThings) doSomethingElseWith(thing);
}
Run Code Online (Sandbox Code Playgroud)

当然,至少有两个缺点:

  1. API背后的代码不能依赖collectionOfThings的不变性,可能会遇到"集合修改"异常或遇到其他其他微妙问题.

  2. 我们不知道collectionOfThings是真实集合还是简单的延迟查询.如果我们假设它是一个真正的集合,那么我们就不会通过运行多个枚举来降低性能.如果我们假设它是一个延迟查询并且它实际上是一个真实的集合,那么将其转换为本地列表或其他冻结集合会产生不必要的成本,尽管它确实有助于保护我们免受第一个问题的影响(执行"ToList"操作时仍存在竞争条件).显然,我们可以编写少量代码来检查这一点,并尝试做"正确的事情",但这是令人讨厌的额外混乱.

我必须承认,除了使用命名约定之外,我从未找到过令人满意的模式来解决这个问题.尽管存在缺点,但是实用的方法似乎是IEnumerable是传递集合的最低摩擦方法.

现在,随着不可变的收藏,情况得到了很大改善......

public void DoSomeEnumerationsWithACollection(ImmutableList<Thing> collectionOfThings)
{ 
Run Code Online (Sandbox Code Playgroud)

不再存在收集修改的风险,并且对多个枚举的性能影响没有任何歧义.

但是,我们显然失去了API的灵活性,因为我们现在必须传入一个ImmutableList.如果我们的客户端有其他类型的可枚举不可变集合,则必须将其复制到ImmutableList中才能被使用,即使我们想要做的只是枚举它.

理想情况下,我们可以使用类似的界面

public void DoSomeEnumerationsWithACollection(IImmutableEnumerable<Thing> collectionOfThings)
Run Code Online (Sandbox Code Playgroud)

但是,当然,除了约定之外,接口不能强制执行不可变性等语义.

使用基类可能会起作用

public void DoSomeEnumerationsWithACollection(ImmutableEnumerableBase<Thing> collectionOfThings)
Run Code Online (Sandbox Code Playgroud)

除了它被认为是创建未密封的不可变类的不良形式,以免子类引入可变性.无论如何,这还没有在BCL中完成.

或者我们可以继续在API中使用IEnumerable并使用命名约定来明确我们的代码依赖于传递的不可变集合.

所以...我的问题是在传递不可变集合时哪些模式被认为是最好的?是ImmutableList "新的IEnumerable "一旦我们开始使用不可变性,或是否有更好的办法?

更新

IReadOnlyCollection(由Yuval Itzchakov建议)是对IEnumerable的明显改进,但仍然没有完全保护消费者免受集合中不受控制的变化的影响.值得注意的是,Roslyn代码库大量使用不变性(主要通过ImmutableArray)并且在将这些传递给其他方法时似乎使用显式类型,尽管有几个位置将ImmutableList传递给接受IEnumerable的方法.

.net c# immutability immutablelist immutable-collections

12
推荐指数
2
解决办法
822
查看次数

按键对ImmutableSortedDictionary范围进行枚举

我正在阅读有关C#的内容ImmutableSortedDictionarySystem.Collections.Immutable并在考虑如何在程序中应用它。我非常喜欢C ++的lower_boundupper_bound(请参阅此处),而我更希望看到某种范围查找。但是,文档中似乎缺少类似的方法。我想念什么吗?还是MS真正提供了分类字典,而没有有效访问分类范围?这似乎并不像对IEnumerable扩展方法那样,可以对其中一个键进行某些操作,所以我有点困惑,因为我没有看到集合直接提供的某些功能。

.net c# algorithm immutability immutable-collections

10
推荐指数
1
解决办法
229
查看次数

Nuget似乎安装了错误版本的System.Collections.Immutable

我和Nuget有一个令人困惑的问题.我有很多项目声称在1.3.0版本上安装了System.Collections.Immutable 但是如果我在所有引用中看到dll的版本,我看到版本1.2.1.0

当我用JustDecompile打开DLL时,我看到了 在此输入图像描述 它声明DLL版本确实是1.2.1.0但已安装在目录包\ System.Collections.Immutable.1.3.0中

典型的packages.config文件将包含

<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net452" />
Run Code Online (Sandbox Code Playgroud)

和csproj是

<Reference 
  Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
     <HintPath>$(SolutionDir)packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
  <Private>True</Private>
</Reference>
Run Code Online (Sandbox Code Playgroud)

如果我尝试从库中打开下载的nuget包并使用nuget package explorer打开,我会得到

在此输入图像描述

c# nuget immutable-collections

9
推荐指数
1
解决办法
5241
查看次数

应该更喜欢ImmutableDictionary还是ImmutableSortedDictionary?

我听说.NET System.Collections.Immutable集合是作为平衡二叉树实现的,以便Dictionary通过使用整数值GetHashCode作为排序键来满足它们的不变性约束,甚至传统上模拟散列表的集合.

如果我有一个类型,它是便宜生成一个散列码,以及对于便宜的比较(如stringint),我不关心我收集整理的烦躁,这将是有意义的喜欢ImmutableSortedDictionary,因为底层数据结构是否仍然排序?

.net c# base-class-library immutable-collections

7
推荐指数
2
解决办法
1523
查看次数

如何从不可变树中获取更改的树,最大化节点的重用

我有这样的树结构数据:

[{
    id: 54,
    name:123,
    children: [{
        id: 54,
        name:123,
        children: [{
            id: 154,
            name:1234,
            children []...
        }]
    }]
}, {
 ...
}]
Run Code Online (Sandbox Code Playgroud)

我正在使用Angular 2.据我所知,无论何时输入发生变化,您的变化检测策略都会发生变化onPush.

为了优化树结构更新(例如,在嵌套级别切换节点或更改此类节点的任何属性),我使用了Immutable.

Immutable如何帮助我优化我的更新?我读到,当数据发生变化时,Immutable会重用旧数据中的引用来构造新对象.

如何有效地使用不可变数据结构来更新嵌套级别的节点?

假设

  1. 我没有keyPath任何节点.
  2. 每个节点都有一个唯一的id属性值,可用于查询树数据(但是如何?)

问题

  1. 如何在嵌套级别更新某个节点?什么是最有效的方式来接触该节点?
  2. 如何更新多个节点?我听说过withMutationsAPI,但还有其他有效的方法吗?

我的方法

  1. 深层复制所有内容,然后修改新构造的对象:

    var newState = deepClone(oldState) // deep copy everything and construct a new object 
    newState.nodes.forEach(node => {
        if(node.id == 54) {
            node.id = 789;
        }
    })
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我想要实现的内容:

    var newState = …
    Run Code Online (Sandbox Code Playgroud)

javascript immutability immutable.js immutable-collections

6
推荐指数
1
解决办法
1195
查看次数