【问题标题】:Why CancellationToken is a struct?为什么 CancellationToken 是一个结构体?
【发布时间】:2018-10-23 05:21:49
【问题描述】:

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

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

同时,就结构而言,它可能被更快地分配和释放。

如果我们想让它不可变,我们可以使用只读属性或私有设置器。

那么它背后的想法是什么?

【问题讨论】:

  • 虽然不是您的问题的直接重复,但对this 问题的接受答案可能会提供一些见解。
  • @pstrjds 这不是我问题的答案。我的问题不在于它是如何更新的,而是.net 架构师为什么决定它应该是一个结构。
  • @Neir0:我仍然对你的反对感到困惑。 结构与引用的大小相同。你是说,“一方面我们必须复制一个小的八字节引用,另一方面,我们必须复制结构的整个八字节 ”。这没有任何意义。你的反对意见是什么?
  • @Eric Lippert 我的错,我没有检查 CancellationToken 的确切大小,它真的很轻量级,我没想到它只有一个字段。感谢您的澄清。
  • @Servy 我听说一般建议值类型大约为 16 个字节,至少以防万一你想将它们作为参数传递。

标签: c# .net cancellation-token


【解决方案1】:

有一篇文章描述了 .NET 取消设计here,值得一读。关于您的问题,在 cmets 中提出以下问题:

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

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

以及 Mike Liddell 的回应:

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

– 每个 CTS/Token 只有一个类实例,因此 GC 压力较小。

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

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

【讨论】:

    【解决方案2】:

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

    是的。

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

    这不是缺点。取消令牌是参考大小的。为什么传递参考大小的结构与传递参考相比会有缺点?这种反对是没有道理的。请解释为什么你认为这是一个“缺点”。

    同时,就结构而言,它可能被更快地分配和释放。

    这是正确的,但实际的胜利更有可能是包装引用的引用大小的结构不会增加收集压力。 .NET 框架中的许多设计和实现决策旨在确保收集压力不会因框架代码而增加太多。

    那么它背后的想法是什么?

    这是一个逻辑上是值的小类型;为什么不应该它是一个值类型?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 2021-11-08
      • 2012-09-09
      • 2018-10-20
      • 2015-09-27
      • 2019-01-16
      相关资源
      最近更新 更多