13

Does it make any sense to use a struct instead of a reference type in case of CancellationToken?

I see one possible disadvantage, it will be copied all the way down in methods chain as I pass it as a parameter.

In the same time, as far as it is struct, it might be allocated and disposed faster.

If we want to make it immutable, we can use readonly properties or private setters.

So what was an idea behind it?

Neir0
  • 12,849
  • 28
  • 83
  • 139
  • 3
    While not a direct duplicate of your question the accepted answer to [this](https://stackoverflow.com/q/48135226/416574) question may offer some insight. – pstrjds Oct 22 '18 at 20:54
  • @pstrjds It is not an answer on my question. My question is not about how it is updated but why .net architectors decided that it should be a struct. – Neir0 Oct 22 '18 at 21:07
  • I note that questions which require a specific person or persons to answer them are not a great fit for Stack Overflow. If there are no .NET architects on Stack Overflow then you are unlikely to get an answer that you will find acceptable and definitive. – Eric Lippert Oct 22 '18 at 21:14
  • Can you explain why you believe that copying the token will be a "disadvantage"? What could possibly be disadvantageous? – Eric Lippert Oct 22 '18 at 21:16
  • This question was already answered here: https://stackoverflow.com/questions/14215784/why-cancellationtoken-is-separate-from-cancellationtokensource#15672264. It is basically preventing the users of the token to set the global state to cancellationrequested. This makes reasoning about who can cancel the async operation much easier in deeply nested library code. – Alois Kraus Oct 22 '18 at 21:18
  • @Eric Lippert Because in case of reference type we have to copy only small reference and in case of struct we have to copy the whole struct. As far as CancellationToken is a very lightweight I guess there should be a big difference but if there are not difference than why struct? – Neir0 Oct 22 '18 at 21:21
  • 1
    @Neir0: I am still confused by your objection. **The struct is the same size as a reference**. You are saying, "on the one hand we have to copy only **a small eight byte reference**, and on the other, we have to copy **the entire eight bytes of the struct**". This doesn't make any sense. What is your objection? – Eric Lippert Oct 22 '18 at 21:24
  • @Eric Lippert There are at least one guy on SO who might know:) – Neir0 Oct 22 '18 at 21:24
  • 1
    @Eric Lippert My bad, I didn't check exact size of CancellationToken, it is really very lightweight, I didn't expect that it has only one field. Thank you for a clarification. – Neir0 Oct 22 '18 at 21:38
  • @Neir0 It's generally a mistake to have a struct that's larger than a reference, at least without a very good reason. – Servy Oct 22 '18 at 21:56
  • 2
    @Servy I heard general recommendation about 16 bytes for value types at least in case if you wanna pass them as a parameter. – Neir0 Oct 23 '18 at 15:11

2 Answers2

18

There is an article that describes the .NET Cancellation design here which is worth a read. In relation to your question, the following is asked in the comments:

Just out of interest, why is the CancellationToken a value type?

and the questioner proposes an alternative implementation with a single shared instance of CancellationToken as a reference type.

And the response by Mike Liddell:

This would certainly work and is largely equivalent (and we implemented it this way during early prototyping), but we went with the current design for two particular reasons:

– only one class instance per CTS/Token, hence less GC pressure.

– we consolidate all of the state and most of the logic onto CTS. The split arrangement was a somewhat more convoluted.

I would note that the current value type implementation is exactly the same size as a reference so there isn't any additional copying overhead. It also prevents some additional boilerplate null checks in user-code, especially when making the token an optional parameter.

Community
  • 1
  • 1
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
9

Does it make any sense to use a struct instead of a reference type in case of CancellationToken?

Yes.

I see one possible disadvantage, it will be copied all the way down in methods chain as I pass it as a parameter.

That is not a disadvantage. A cancellation token is reference-sized. Why would there be a disadvantage of passing a reference-sized struct vs passing a reference? This objection doesn't make sense. Please explain why you think this is a "disadvantage".

In the same time, as far as it is struct, it might be allocated and disposed faster.

That's correct, but the actual win is more likely that a reference-sized struct that wraps a reference does not increase collection pressure. Many of the design and implementation decisions in the .NET framework are designed to ensure that collection pressure is not increased too much by framework code.

So what was an idea behind it?

It's a small type that is logically a value; why shouldn't it be a value type?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067