markdown fixes for 7.3 proposals
These were: 1. adding `csharp` as the language identifier. 1. making relative links to content published on docs.microsoft.com 1. small grammar fixes.
This commit is contained in:
parent
68a95404a1
commit
f69b012846
|
@ -15,7 +15,7 @@ Currently it is not possible to apply attributes to the backing fields of auto-i
|
|||
|
||||
In short, the following would be legal C# and not produce a warning:
|
||||
|
||||
```cs
|
||||
```csharp
|
||||
[Serializable]
|
||||
public class Foo
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ public class Foo
|
|||
|
||||
This would result in the field-targeted attributes being applied to the compiler-generated backing field:
|
||||
|
||||
```cs
|
||||
```csharp
|
||||
[Serializable]
|
||||
public class Foo
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ public class Foo
|
|||
|
||||
As mentioned, this brings parity with event syntax from C# 1.0 as the following is already legal and behaves as expected:
|
||||
|
||||
```cs
|
||||
```csharp
|
||||
[Serializable]
|
||||
public class Foo
|
||||
{
|
||||
|
@ -67,5 +67,3 @@ There are two potential drawbacks to implementing this change:
|
|||
[unresolved]: #unresolved-questions
|
||||
|
||||
## Design meetings
|
||||
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ The unmanaged constraint feature will give language enforcement to the class of
|
|||
|
||||
The primary motivation is to make it easier to author low level interop code in C#. Unmanaged types are one of the core building blocks for interop code, yet the lack of support in generics makes it impossible to create re-usable routines across all unmanaged types. Instead developers are forced to author the same boiler plate code for every unmanaged type in their library:
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
int Hash(Point point) { ... }
|
||||
int Hash(TimeSpan timeSpan) { ... }
|
||||
```
|
||||
|
||||
To enable this type of scenario the language will be introducing a new constraint: unmanaged:
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
void Hash<T>(T value) where T : unmanaged
|
||||
{
|
||||
...
|
||||
|
@ -26,7 +26,7 @@ void Hash<T>(T value) where T : unmanaged
|
|||
|
||||
This constraint can only be met by types which fit into the unmanaged type definition in the C# language spec. Another way of looking at it is that a type satisfies the unmanaged constraint iff it can also be used as a pointer.
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
Hash(new Point()); // Okay
|
||||
Hash(42); // Okay
|
||||
Hash("hello") // Error: Type string does not satisfy the unmanaged constraint
|
||||
|
@ -34,8 +34,7 @@ Hash("hello") // Error: Type string does not satisfy the unmanaged constraint
|
|||
|
||||
Type parameters with the unmanaged constraint can use all the features available to unmanaged types: pointers, fixed, etc ...
|
||||
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
void Hash<T>(T value) where T : unmanaged
|
||||
{
|
||||
// Okay
|
||||
|
@ -48,7 +47,7 @@ void Hash<T>(T value) where T : unmanaged
|
|||
|
||||
This constraint will also make it possible to have efficient conversions between structured data and streams of bytes. This is an operation that is common in networking stacks and serialization layers:
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
Span<byte> Convert<T>(ref T value) where T : unmanaged
|
||||
{
|
||||
...
|
||||
|
@ -71,7 +70,7 @@ Compiler generated instance fields, such as those backing auto-implemented prope
|
|||
|
||||
For example:
|
||||
|
||||
``` c#
|
||||
```csharp
|
||||
// Unmanaged type
|
||||
struct Point
|
||||
{
|
||||
|
@ -121,7 +120,7 @@ There are a couple of alternatives to consider:
|
|||
The F# language encodes the constraint in the signature file which means C# cannot re-use their representation. A new attribute will need to be chosen for this constraint. Additionally a method which has this constraint must be protected by a mod-req.
|
||||
|
||||
### Blittable vs. Unmanaged
|
||||
The F# language has a very [similar feature](https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/constraints) which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead.
|
||||
The F# language has a very [similar feature](https://docs.microsoft.com/dotnet/articles/fsharp/language-reference/generics/constraints) which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead.
|
||||
|
||||
**Resolution** The language decide to use unmanaged
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# expression variables in initializers
|
||||
# Expression variables in initializers
|
||||
|
||||
## Summary
|
||||
[summary]: #summary
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
# Indexing `fixed` fields should not require pinning regardless of the movable/unmovable context. #
|
||||
|
||||
The change has the size of a bug fix. It can be in 7.3 and does not conflict with whatever direction we take further.
|
||||
|
@ -6,7 +5,7 @@ This change is only about allowing the following scenario to work even though `s
|
|||
|
||||
NOTE: in either case, it still requires `unsafe` context. It is possible to read uninitialized data or even out of range. That is not changing.
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
unsafe struct S
|
||||
{
|
||||
public fixed int myFixedField[10];
|
||||
|
@ -27,7 +26,7 @@ The main “challenge” that I see here is how to explain the relaxation in the
|
|||
In particular, since the following would still need pinning.
|
||||
(because `s` is moveable and we explicitly use the field as a pointer)
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
unsafe struct S
|
||||
{
|
||||
public fixed int myFixedField[10];
|
||||
|
@ -48,5 +47,3 @@ class Program
|
|||
One reason why we require pinning of the target when it is movable is the artifact of our code generation strategy, - we always convert to an unmanaged pointer and thus force the user to pin via `fixed` statement. However, conversion to unmanaged is unnecessary when doing indexing. The same unsafe pointer math is equally applicable when we have the receiver in the form of a managed pointer. If we do that, then the intermediate ref is managed (GC-tracked) and the pinning is unnecessary.
|
||||
|
||||
The change https://github.com/dotnet/roslyn/pull/24966 is a prototype PR that relaxes this requirement.
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Introduce a pattern that would allow types to participate in `fixed` statements.
|
|||
|
||||
The language provides a mechanism for pinning managed data and obtain a native pointer to the underlying buffer.
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
fixed(byte* ptr = byteArray)
|
||||
{
|
||||
// ptr is a native pointer to the first element of the array
|
||||
|
@ -39,12 +39,12 @@ I think the above could be satisfied by recognizing a specially named ref-return
|
|||
|
||||
In order to be used by the `fixed` statement the following conditions must be met:
|
||||
|
||||
1) There is only one such member provided for a type.
|
||||
1) Returns by `ref` or `ref readonly`.
|
||||
1. There is only one such member provided for a type.
|
||||
1. Returns by `ref` or `ref readonly`.
|
||||
(`readonly` is permitted so that authors of immutable/readonly types could implement the pattern without adding writeable API that could be used in safe code)
|
||||
1) T is an unmanaged type.
|
||||
1. T is an unmanaged type.
|
||||
(since `T*` becomes the pointer type. The restriction will naturally expand if/when the notion of "unmanaged" is expanded)
|
||||
1) Returns managed `nullptr` when there is no data to pin – probably the cheapest way to convey emptiness.
|
||||
1. Returns managed `nullptr` when there is no data to pin – probably the cheapest way to convey emptiness.
|
||||
(note that “” string returns a ref to '\0' since strings are null-terminated)
|
||||
|
||||
Alternatively for the `#3` we can allow the result in empty cases be undefined or implementation-specific.
|
||||
|
@ -52,23 +52,22 @@ That, however, may make the API more dangerous and prone to abuse and unintended
|
|||
|
||||
## *Translation* ##
|
||||
|
||||
```C#
|
||||
fixed(byte* ptr = thing)
|
||||
{
|
||||
```csharp
|
||||
fixed(byte* ptr = thing)
|
||||
{
|
||||
// <BODY>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
becomes the following pseudocode (not all expressible in C#)
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
byte* ptr;
|
||||
// specially decorated "pinned" IL local slot, not visible to user code.
|
||||
pinned ref byte _pinned;
|
||||
|
||||
byte* ptr;
|
||||
// specially decorated "pinned" IL local slot, not visible to user code.
|
||||
pinned ref byte _pinned;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// NOTE: null check is omitted for value types
|
||||
// NOTE: `thing` is evaluated only once (temporary is introduced if necessary)
|
||||
if (thing != null)
|
||||
|
@ -85,16 +84,14 @@ becomes the following pseudocode (not all expressible in C#)
|
|||
}
|
||||
|
||||
// <BODY>
|
||||
}
|
||||
finally // finally can be omitted when not observable
|
||||
{
|
||||
}
|
||||
finally // finally can be omitted when not observable
|
||||
{
|
||||
// "unpin" the object
|
||||
_pinned = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Drawbacks
|
||||
[drawbacks]: #drawbacks
|
||||
|
||||
|
@ -105,11 +102,11 @@ becomes the following pseudocode (not all expressible in C#)
|
|||
|
||||
Users can introduce GetPinnableReference or similar member and use it as
|
||||
|
||||
```C#
|
||||
fixed(byte* ptr = thing.GetPinnableReference())
|
||||
{
|
||||
```csharp
|
||||
fixed(byte* ptr = thing.GetPinnableReference())
|
||||
{
|
||||
// <BODY>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There is no solution for `System.String` if alternative solution is desired.
|
||||
|
|
|
@ -4,7 +4,7 @@ In C# 7.3, we add support for rebinding the referent of a ref local variable or
|
|||
|
||||
We add the following to the set of `assignment_operator`s.
|
||||
|
||||
``` antlr
|
||||
```antlr
|
||||
assignment_operator
|
||||
: '=' 'ref'
|
||||
;
|
||||
|
@ -24,4 +24,4 @@ The safety rules for this operator are:
|
|||
|
||||
- For a ref reassignment `e1 = ref e2`, the *ref-safe-to-escape* of `e2` must be at least as wide a scope as the *ref-safe-to-escape* of `e1`.
|
||||
|
||||
Where *ref-safe-to-escape* is defined in https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md
|
||||
Where *ref-safe-to-escape* is defined in [Safety for ref-like types](../csharp-7.2/span-safety.md)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# Stackalloc array initializers.
|
||||
# Stackalloc array initializers
|
||||
|
||||
## Summary
|
||||
[summary]: #summary
|
||||
|
||||
Allow array initializer syntax to be used with `stackalloc`
|
||||
Allow array initializer syntax to be used with `stackalloc`.
|
||||
|
||||
## Motivation
|
||||
[motivation]: #motivation
|
||||
|
@ -11,13 +11,13 @@ Allow array initializer syntax to be used with `stackalloc`
|
|||
Ordinary arrays can have their elements initialized at creation time. It seems reasonable to allow that in `stackalloc` case.
|
||||
|
||||
The question of why such syntax is not allowed with `stackalloc` arises fairly frequently.
|
||||
See, for example, https://github.com/dotnet/csharplang/issues/1112
|
||||
See, for example, [#1112](https://github.com/dotnet/csharplang/issues/1112)
|
||||
|
||||
## Detailed design
|
||||
|
||||
Ordinary arrays can be created through the following syntax:
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
new int[3]
|
||||
new int[3] { 1, 2, 3 }
|
||||
new int[] { 1, 2, 3 }
|
||||
|
@ -26,7 +26,7 @@ new[] { 1, 2, 3 }
|
|||
|
||||
We should allow stack allocated arrays be created through:
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
stackalloc int[3] // currently allowed
|
||||
stackalloc int[3] { 1, 2, 3 }
|
||||
stackalloc int[] { 1, 2, 3 }
|
||||
|
@ -38,7 +38,7 @@ For example: in the last case the element type is inferred from the initializer
|
|||
|
||||
NOTE: the feature is not dependent on the target being a `Span<T>`. It is just as applicable in `T*` case, so it does not seem reasonable to predicate it on `Span<T>` case.
|
||||
|
||||
## Translation ##
|
||||
## Translation
|
||||
|
||||
The naive implementation could just initialize the array right after creation through a series of element-wise assignments.
|
||||
|
||||
|
|
|
@ -73,5 +73,5 @@ If someone wrote their own `ValueTuple` types with an implementation of the com
|
|||
|
||||
----
|
||||
|
||||
Relates to https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#relational-and-type-testing-operators
|
||||
Relates to https://github.com/dotnet/csharplang/issues/190
|
||||
Relates to [relational and type testing operators](../../spec/expressions.md#relational-and-type-testing-operators)
|
||||
Relates to [#190](https://github.com/dotnet/csharplang/issues/190)
|
||||
|
|
Loading…
Reference in a new issue