Features are already being lined up for C# 7.2 and 8.0 including nullable reference types and limited multiple inheritance.
Read-Only References and Structs [7.2 Prototype]
First up are Read-Only References and Structs. Briefly, this gives C# the ability to use const-like parameters to improve performance. Known as “ref readonly parameters” or simple “in parameters”, these allow large structs to be passed by reference while not allowing them to be mutated.
Part of this proposal are readonly structs. By marking a struct as readonly, the developer is indicating that none of the methods on that struct can modify it. This has performance ramifications, as it indicates to the compiler that it can skip copying operations it would ordinarily use to prevent the accidental modification of a readonly variable.
Blittable Types [7.2 Proposal]
Wikipedia described blittable types as,
Data are often represented in memory differently in managed and unmanaged code in the Microsoft .NET framework. However, blittable types are defined as having an identical presentation in memory for both environments, and can be directly shared.
Non-blittable types include Boolean, string, char, and any reference type. If a stuct contains one of these types, the struct itself is also non-blittable.
Currently the C# compiler infers whether or not a given type is blittable by examining its structure. This has caused problems in the past, as adding a new field could make a blittable type non-blittable, which is a breaking change in some circumstances.
Under the Blittable Types proposal, the “blittable” keyword can be added to explicitly indicate a struct is blittable. If the type is later modified in a way that makes it non-blittable, a compiler error will occur.
In order to ensure backwards compatibility over the long run, structs marked as blittable may only contain other struts that are likewise explicitly marked as blittable. Furthermore, the struct may not use StructLayout(LayoutKind.Auto)]. This refers to how the struct is physically arranged in memory. Explicit and sequential layouts are both allowed.
Note: changing the LayoutKind or Pack setting on a struct is considered to be a breaking change, as it would alter how unmanaged code would see the struct.
Microsoft is concerned about the transitional period for this feature. Low level libraries will have to adopt the use of explicitly blittable types before higher level libraries that use them can.
Compile time enforcement of safety for ref-like types [7.2 Proposal]
This C# feature is also known as “interior pointer” or “ref-like types”. The proposal is to allow the compiler to require that certain types such as Span<T> only appear on the stack. It cites several reasons for this:
1. Span<T> is semantically a struct containing a reference and a range - (ref T data, int length). Regardless of actual implementation, writes to such struct would not be atomic. Concurrent "tearing" of such struct would lead to the possibility of length not matching the data, causing out-of-range accesses and type-safety violations, which ultimately could result in GC heap corruption in seemingly "safe" code.
2. Some implementations of Span<T> literally contain a managed pointer in one of its fields. Managed pointers are not supported as fields of heap objects and code that manages to put a managed pointer on the GC heap typically crashes at JIT time.
3. It is permitted for a Span<T> to refer to data in the local stack frame - individual local variables or stackalloc-ed arrays. A scenario when an instance of a Span<T> outlives the referred data would lead to undefined behavior, including type-safety violations and heap corruptions.
The ref-like types have several usage restrictions:
- ref-like type cannot be a type of an array element
- ref-like type cannot be used as a generic type argument
- ref-like variable cannot be boxed
- ref-like type cannot be a field of ordinary not ref-like type
- indirect restrictions, such as disallowed use of ref-like types in async methods, which are really a result of disallowing ref-like typed fields.
Effectively this means that ref-like types can only be used for parameters, local variables, and in some cases return values. A ref-like type can contain another ref-like type.
All ref-like types are also readonly structs (see above).
Like ref types, ref-like types may end up being “single-assignment”. The proposal notes other ways to ensure safely, but this puts the least burden on the compiler.
C# 8.0 Prototypes
Two features for C# 8 have already hit the prototype phase:
- Nullable Reference Types: This makes reference types non-nullable by default. For a nullable reference type variable, you would use T? just as you would for a nullable struct.
- Default Interface Methods: This adds a limited form of multiple inheritance to C#.