Merge pull request #2313 from BillWagner/markdown-lint-csharp71
markdown lint for C# 7.1 proposals
This commit is contained in:
commit
5c53f8687e
3 changed files with 21 additions and 10 deletions
|
@ -17,7 +17,8 @@ It is very common when learning C#, when writing console-based utilities, and wh
|
|||
to call and `await` `async` methods from Main. Today we add a level of complexity here by forcing such `await`'ing to be
|
||||
done in a separate async method, which causes developers to need to write boilerplate like the following just to get
|
||||
started:
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
public static void Main()
|
||||
{
|
||||
MainAsync().GetAwaiter().GetResult();
|
||||
|
@ -28,6 +29,7 @@ private static async Task MainAsync()
|
|||
... // Main body here
|
||||
}
|
||||
```
|
||||
|
||||
We can remove the need for this boilerplate and make it easier to get started simply by allowing Main itself to be
|
||||
`async` such that `await`s can be used in it.
|
||||
|
||||
|
@ -35,7 +37,8 @@ We can remove the need for this boilerplate and make it easier to get started si
|
|||
[design]: #detailed-design
|
||||
|
||||
The following signatures are currently allowed entrypoints:
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
static void Main()
|
||||
static void Main(string[])
|
||||
static int Main()
|
||||
|
@ -43,12 +46,14 @@ static int Main(string[])
|
|||
```
|
||||
|
||||
We extend the list of allowed entrypoints to include:
|
||||
```
|
||||
|
||||
```csharp
|
||||
static Task Main()
|
||||
static Task<int> Main()
|
||||
static Task Main(string[])
|
||||
static Task<int> Main(string[])
|
||||
```
|
||||
|
||||
To avoid compatibility risks, these new signatures will only be considered as valid entrypoints if no overloads of the previous set are present.
|
||||
The language / compiler will not require that the entrypoint be marked as `async`, though we expect the vast majority of uses will be marked as such.
|
||||
|
||||
|
@ -59,7 +64,8 @@ When one of these is identified as the entrypoint, the compiler will synthesize
|
|||
- ```static Task<int> Main(string[])``` will result in the compiler emitting the equivalent of ```private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();```
|
||||
|
||||
Example usage:
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
|
@ -81,14 +87,17 @@ The main drawback is simply the additional complexity of supporting additional e
|
|||
Other variants considered:
|
||||
|
||||
Allowing `async void`. We need to keep the semantics the same for code calling it directly, which would then make it difficult for a generated entrypoint to call it (no Task returned). We could solve this by generating two other methods, e.g.
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
public static async void Main()
|
||||
{
|
||||
... // await code
|
||||
}
|
||||
```
|
||||
|
||||
becomes
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
public static async void Main() => await $MainTask();
|
||||
|
||||
private static void $EntrypointMain() => Main().GetAwaiter().GetResult();
|
||||
|
@ -98,6 +107,7 @@ private static async Task $MainTask()
|
|||
... // await code
|
||||
}
|
||||
```
|
||||
|
||||
There are also concerns around encouraging usage of `async void`.
|
||||
|
||||
Using "MainAsync" instead of "Main" as the name. While the async suffix is recommended for Task-returning methods, that's primarily about library functionality, which Main is not, and supporting additional entrypoint names beyond "Main" is not worth it.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
## Summary
|
||||
[summary]: #summary
|
||||
|
||||
The specification for the [existing C# as operator](https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#the-as-operator) permits there to be no conversion between the type of the operand and the specified type when either is an open type. However, in C# 7 the `Type identifier` pattern requires there be a conversion between the type of the input and the given type.
|
||||
The specification for the [existing C# as operator](../../spec/expressions.md#the-as-operator) permits there to be no conversion between the type of the operand and the specified type when either is an open type. However, in C# 7 the `Type identifier` pattern requires there be a conversion between the type of the input and the given type.
|
||||
|
||||
We propose to relax this and change `expression is Type identifier`, in addition to being permitted in the conditions when it is permitted in C# 7, to also be permitted when `expression as Type` would be allowed. Specifically, the new cases are cases where the type of the expression or the specified type is an open type.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ This parallels the behavior of anonymous types, which allow inferring member na
|
|||
|
||||
This is particularly handy when using tuples in LINQ:
|
||||
|
||||
```
|
||||
```csharp
|
||||
// "c" and "result" have element names "f1" and "f2"
|
||||
var result = list.Select(c => (c.f1, c.f2)).Where(t => t.f2 == 1);
|
||||
```
|
||||
|
@ -30,7 +30,8 @@ There are two parts to the change:
|
|||
Note that the rule for handling duplicates is different than that for anonymous types. For instance, `new { x.f1, x.f1 }` produces an error, but `(x.f1, x.f1)` would still be allowed (just without any inferred names). This avoids breaking existing tuple code.
|
||||
|
||||
For consistency, the same would apply to tuples produced by deconstruction-assignments (in C#):
|
||||
```C#
|
||||
|
||||
```csharp
|
||||
// tuple has element names "f1" and "f2"
|
||||
var tuple = ((x.f1, x?.f2) = (1, 2));
|
||||
```
|
||||
|
@ -44,7 +45,7 @@ When using the C# 7.1 compiler (or later) with language version "7.0", the eleme
|
|||
|
||||
The main drawback is that this introduces a compatibility break from C# 7.0:
|
||||
|
||||
```C#
|
||||
```csharp
|
||||
Action y = () => M();
|
||||
var t = (x: x, y);
|
||||
t.y(); // this might have previously picked up an extension method called “y”, but would now call the lambda.
|
||||
|
|
Loading…
Reference in a new issue