为什么CancellationToken是一个结构?

时间:2018-10-22 20:50:34

标签: c# .net cancellation-token

在CancellationToken的情况下,使用结构而不是引用类型有意义吗?

我看到一个可能的缺点,当我将其作为参数传递时,它将在方法链中一直复制到最下面。

同时,就结构而言,它可能会更快地分配和处置。

如果我们想使其不可变,则可以使用只读属性或私有设置程序。

那么背后的想法是什么?

2 个答案:

答案 0 :(得分:7)

有一篇文章描述了.NET取消设计here,值得一读。关于您的问题,在评论中要求以下内容:

  

只是出于兴趣,为什么CancellationToken是一种值类型?

并且提问者提出了一个替代实现,其中将CancellationToken的单个共享实例作为引用类型。

以及Mike Liddell的回复:

  

这肯定会起作用,并且在很大程度上是等效的(并且我们在早期原型制作中以这种方式实现了),但是出于两个特殊原因,我们选择了当前设计:

     

–每个CTS /令牌仅一个类实例,因此,GC压力较小。

     

–我们将所有状态和大多数逻辑整合到CTS上。拆分安排有些复杂。

我会注意到,当前值类型的实现与引用的大小完全相同,因此没有任何额外的复制开销。它还可以防止在用户代码中进行一些额外的样板空检查,尤其是在将令牌设为可选参数时。

答案 1 :(得分:3)

  

在CancellationToken的情况下,使用结构而不是引用类型有意义吗?

是的

  

我看到一个可能的缺点,当我将其作为参数传递时,它将一直复制到方法链中。

这不是缺点。取消令牌为参考大小。为什么通过引用大小的结构与通过引用相比会有缺点?这种反对是没有道理的。请说明为什么您认为这是“不利条件”。

  

同时,就结构而言,它可能会更快地分配和处置。

是正确的,但是实际的获胜更有可能是包裹引用的引用大小的结构不会增加收集压力。 .NET框架中的许多设计和实现决策都是为了确保框架代码不会过多增加收集压力。

  

那背后的想法是什么?

这是一个小类型,从逻辑上讲是一个值;为什么不应该是值类型?