BT

Your opinion matters! Please fill in the InfoQ Survey!

C# Futures: Read-Only References and Structs

| by Jonathan Allen Follow 189 Followers on Apr 19, 2017. Estimated reading time: 4 minutes |

In C++ we have a feature known as “const”. This can be applied to parameters so that the caller knows that function will not modify the parameter and/or the object the parameter references (it’s actually more complicated than this. For more information see Const Correctness). Under this proposal, C# would get something similar.

Read-Only Ref Parameters

Also known as “in parameters”, readonly references would allow similar restrictions in C#. The basic idea is that you can mark a parameter as “readonly ref” or just “in” and the compiler would understand it as “pass this parameter by reference to improve performance, but don’t allow it to actually be changed”. This feature would be of particular use for large structs in high-performance scenarios. The proposal cites the following examples:

Vector/matrix math operators in graphics libraries like XNA are known to have ref operands purely because of performance considerations. There is code in Roslyn compiler itself that uses structs to avoid allocations and then passes them by reference to avoid copying costs.

This syntax would combine both of the C++ versions of const. Neither the parameter itself can be modified, nor can any of the data in the object or struct it references.

Currently, you have to use the “ref” or “out” keyword when passing a parameter by reference. Under this proposal, that requirement won’t apply for “in” parameters. Furthermore, you could pass in the result of an expression (this is currently allowed by VB, not but C#).

Implementation Details

Overloading rules will work in the same way as it does today, for ref vs out parameters.

It is still up for debate, but currently the plan is to not allow “in” parameters to be captured by anonymous or async functions (i.e. making a closure object). The problem with capturing an “in” parameter is that it will cause a copy to be made, which defeats the purpose of using “in” to avoid the performance cost of copies.

Marking a parameter as “readonly ref” or “in” does not make the value it refers to immutable. While the function declaring the parameter cannot make changes to it, the value can be changed elsewhere. This doesn’t require multiple-threads, just a way to access the original variable the parameter refers to.

Calling methods on a struct can be problematic. From the proposal:

Since all regular instance methods of a struct can potentially mutate the instance or ref-expose this, an intermediate copy must be created, as already a case when a  receiver is a readonly field.

However, since there is no backward compatibility considerations and there are workarounds, the compiler should give a warning to ensure the implicit copying is noted by the user.

As with “out” parameters, a special attribute would indicate that an “in” parameter is desired. Older compilers would ignore this parameter so there is no backwards compatibility issue.

Read-Only Ref Returns

Closely related to this feature is the ability to mark ref returns as read-only. As with “in” parameters, the main reason for this feature is performance. However, in this case you would not be allowed to return the results of an expression. It has to be a legal variable for a normal ref return, which would include array elements, ref parameters, and fields in objects.

ref/in Extension Methods

“ref” extension methods would allow said extension method to modify the struct that is passed in. The compiler would need to be able to prove that an argument passed to a ref extension method would need to be mutable.

“in” extension methods would not allow for modifications, but would still be useful for performance sensitive code, especially if the struct is large. This would of course not require a mutable argument.

In both cases, this feature would only be available for structs.

Editors note: presumably if the Pure attribute were widely used, the compiler could then disallow calling non-pure methods for “in” extension methods. However, this would not improve performance so it isn’t as likely to happen.

Read-Only Structs

Marking a struct variable as read-only can have performance ramifications. The compiler doesn’t know if a given method call can modify the struct, so it assumes that it will and always makes a copy of the readonly struct variable.

With this feature, you would be able to mark the whole struct as read-only at the type level. By making this promise, you tell the compiler that copies are not necessary when the readonly stuct is exposed via a readonly struct variable.

The proposal notes:

The only obvious question is whether there is a need for an option to opt out some of the methods as mutators.

So far it feels like per-member control over readonly is an unnecessary complication, which also can be added later if found to be necessary.

Current assumptions are that "Mixed" mutable/immutable structs are not common. Besides, even partially mutable struct variables would generally need to be LValues and thus would not impacted by the implicit copying.

Drawbacks

The proposal notes that these features would be unlikely to benefit existing code, but could be useful in new scenarios such as:

  • cloud/datacenter scenarios where computation is billed for and responsiveness is a competitive advantage.
  • Games/VR/AR with soft-realtime requirements on latencies

It also warns that the function being called can circumnavigate the restrictions on “in” parameters, but that is a only minor concern because they can already do the same with “out” parameters.

Rate this Article

Adoption Stage
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Read-Only Ref Returns by David Smith

"However, in this case you would not be allowed to return the results of an expression."

I'd like to find out more about how/why this is a restriction for the feature. Is there a relevant GitHub issue link where this feature's being discussed?

Re: Read-Only Ref Returns by Pierre-Luc Maheu

Yes, the discussion is on another GitHub issue: github.com/dotnet/roslyn/issues/115. There's also a followup since the discussion is two years old: github.com/dotnet/csharplang/issues/188

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

2 Discuss

Login to InfoQ to interact with what matters most to you.


Recover your password...

Follow

Follow your favorite topics and editors

Quick overview of most important highlights in the industry and on the site.

Like

More signal, less noise

Build your own feed by choosing topics you want to read about and editors you want to hear from.

Notifications

Stay up-to-date

Set up your notifications and don't miss out on content that matters to you

BT