Created Available C#/.NET features (markdown)

James Groom 2022-07-08 03:30:05 +10:00
parent ec7a889149
commit 179fcaa4cd
1 changed files with 125 additions and 0 deletions

@ -0,0 +1,125 @@
This document is to supplement BizHawk development, and will be deleted once the project is on .NET Core. Yoshi will maintain [a copy on GitLab](https://gitlab.com/-/snippets/2367119) for the benefit of other projects.
BizHawk-specific notes:
- All projects in the main BizHawk solution use C# 9 currently.
- In the added "convention" column, I've used required/disallowed/encouraged/discouraged/allowed like [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119)'s MUST / MUST NOT / SHOULD / SHOULD NOT / MAY, respectively. Unsupported is also MUST NOT (because attempting to use the feature will result in an error).
- Each project's target (Framework vs. Standard) is at the top of its project file, or you can check the [project graph](https://gitlab.com/TASVideos/BizHawk/-/snippets/1886666).
Legend:
✔️ Available
⭕ Available with polyfill
❌ Not available
? Unknown
🔵 Availablity in .NET Framework 4.8 (`net48`)
🟢 Availablity in .NET Standard 2.0 (`netstandard2.0`)
I have not considered Framework 4.7.2 and below as there is little reason to not upgrade to Framework 4.8.
I use Standard 2.0 and not Standard 2.1 because Standard 2.1 is not subsumed by Framework 4.8, rendering it useless.
> Note: "deconstructing" is what .NET calls "destructuring"; not to be confused with "destructing" which .NET calls "finalising".
Feature | 🔵 `net48` | 🟢 `ns2.0` | convention for main BizHawk solution
--:|:-:|:-:|:--
[enhanced `nameof`](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#extended-nameof-scope) | ? | ? | unsupported
[pattern matching for `Span<char>`](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#pattern-match-spanchar-or-readonlyspanchar-on-a-constant-string) | ? | ? | unsupported
Kotlin-like [raw string literals](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#raw-string-literals) | ? | ? | unsupported
[list pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#list-patterns) | ? | ? | unsupported
[multi-line expressions in interpolated strings](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#newlines-in-string-interpolations) | ? | ? | unsupported
[generic maths](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-math-support) using [static abstract members](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-abstract-interface-methods) | ? | ? | unsupported
[genericised attributes](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-attributes) | ? | ? | unsupported
^ C# 11 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
per-method [`AsyncMethodBuilder`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#asyncmethodbuilder-attribute) | ? | ? | unsupported
[enhanced `null` analysis](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#improved-definite-assignment) | ? | ? | unsupported
[enhanced destructuring](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#assignment-and-declaration-in-same-deconstruction) | ✔️ | ✔️ | unsupported
[`sealed` `ToString` in records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#built-in-formatting-for-display) | ? | ? | unsupported
limited string interpolation in [consts](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const) | ✔️ | ✔️ | unsupported
[attributes for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#attributes) | ✔️ | ✔️ | unsupported
[type inference for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#natural-type-of-a-lambda-expression) | ✔️ | ✔️ | unsupported
[pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern) IV | ✔️ | ✔️ | unsupported
[`namespace A;`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace) | ✔️ | ✔️ | unsupported
[`global using A;`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#global-modifier)/[`<Using>`](https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#using) | ✔️ | ✔️ | unsupported
[custom interpolated string handlers](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler) | ? | ? | unsupported
[`with` for structs](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | unsupported
[enhanced struct field init](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#struct-initialization-and-default-values) | ✔️ | ✔️ | unsupported
[`record struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) | ✔️ | ✔️ | unsupported
^ C# 10 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
enhanced [partial methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-method) | ? | ? | unsupported
[`[ModuleInitializer]` method](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#moduleinitializer-attribute) | ⭕ | ⭕ | unsupported
[attributes on local methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/local-function-attributes) | ✔️ | ✔️ | allowed
[discarding](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards) lambda parameters | ✔️ | ✔️ | encouraged
[`foreach` picks up `GetEnumerator` extension](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/extension-getenumerator) | ✔️ | ✔️ | discouraged (surely this can only be used for stupid)
[covariant return type when overriding](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/covariant-returns) | ❌ | ❌ | unsupported
[enhanced type inference](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-typed-conditional-expression) | ✔️ | ✔️ | omit explicit type cast where possible, otherwise place the cast on default branch of `switch` and first branch of ternary
[`static` lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#capture-of-outer-variables-and-variable-scope-in-lambda-expressions) | ✔️ | ✔️ | encouraged
target-typed [`new()`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/new-operator#constructor-invocation) | ✔️ | ✔️ | encouraged
[function pointers](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers) | ? | ? | unsupported
[`nint`/`nuint`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#native-sized-integers) | ✔️ | ✔️ | allowed
[pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#logical-patterns) III | ✔️ | ✔️ | encouraged
[unindented `Main`](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements) | ? | ? | N/A (neither executable uses it)
[`with` for records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | discouraged
[`init`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init) | ✔️ | ✔️ | discouraged
[`record class`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) | ✔️ | ✔️ | discouraged
^ C# 9 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
`@$""` (instead of `$@""`) | ✔️ | ✔️ | disallowed
[`stackalloc`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc) as arg for `Span` param | ✔️ | ✔️ | allowed
[`??=`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator) | ✔️ | ✔️ | encouraged
[`Index` and `Range` (`^` and `..` operators)](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#index-from-end-operator-) | ⭕ | ⭕ | unsupported (we have a generic `Range<T>` but it has some problems, like not working with `..`)
[async streams](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream) | ⭕ | ⭕ | unknown
NRTs (attribute-based analysis) | ⭕ | ⭕ | encouraged
NRTs (syntax and basic analysis) | ✔️ | ✔️ | encouraged for new files, see [project graph](https://gitlab.com/TASVideos/BizHawk/-/snippets/1886666) for when `#nullable enable` is needed
static [local methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions) | ✔️ | ✔️ | encouraged
[`using` statement](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement) without block | ✔️ | ✔️ | encouraged
[pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern) II | ✔️ | ✔️ | encouraged
[`switch` expression](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression) | ✔️ | ✔️ | encouraged
[default interface methods](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions) | ❌ | ❌ | unsupported
[`readonly` methods/getters/setters](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#readonly-instance-members) | ✔️ | ✔️ | encouraged
^ C# 8 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
`field` [attribute target](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/#attribute-targets) for auto-prop backing field | ✔️ | ✔️ | discouraged (surely this can only be used for stupid)
[`stackalloc`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc) with array intialiser | ✔️ | ✔️ | encouraged
^ C# 7.3 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`ref struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#ref-struct) (stack-bound) | ✔️ | ✔️ | allowed
[`readonly struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#readonly-struct) and `in` parameters | ✔️ | ✔️ | encouraged
^ C# 7.2 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[inferred tuple field names](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples#tuple-field-names) | ✔️ | ✔️ | discouraged
[`default` without type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/default#default-literal) | ✔️ | ✔️ | encouraged for non-nullable value types, discouraged otherwise
[`async` `Main`](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#async-main-return-values) | ? | ? | N/A (neither executable uses it)
^ C# 7.1 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`throw` expression](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/throw#the-throw-expression) | ✔️ | ✔️ | encouraged
[enhanced int literals](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#integer-literals) | ✔️ | ✔️ | encouraged
[discards](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards) | ✔️ | ✔️ | encouraged
[`ref` returns/locals](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/ref-returns) | ✔️ | ✔️ | allowed
[expression-bodied ctors](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members#constructors) | ✔️ | ✔️ | encouraged
[local methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions) | ✔️ | ✔️ | encouraged
basic [pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching) | ✔️ | ✔️ | encouraged
[`KeyValuePair<K, V>.Deconstruct`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair-2.deconstruct?view=net-6.0) | ⭕ | ⭕ | allowed
basic [tuples and destructuring](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples) | ✔️ | ✔️ | encouraged
[`out var`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier#calling-a-method-with-an-out-argument) | ✔️ | ✔️ | encouraged
^ C# 7.0 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`nameof`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/nameof) | ✔️ | ✔️ | encouraged
[interpolated string literals](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated) | ✔️ | ✔️ | preferred over `string.Format` or concatenation
[null-conditional member access](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-) | ✔️ | ✔️ | required
[expression-bodied methods/props](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members#methods) | ✔️ | ✔️ | encouraged
inline initialisation of [auto-props](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties) | ✔️ | ✔️ | encouraged
[`catch (Exception e) when (predicate(e))`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/when#when-in-a-catch-statement) | ✔️ | ✔️ | encouraged
[`using static A;`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#static-modifier) | ✔️ | ✔️ | allowed only for the file's own namespace
^ C# 6 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`[Caller*]`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information) | ✔️ | ✔️ | allowed
[`async`](https://docs.microsoft.com/en-us/dotnet/csharp/async) | ✔️ | ✔️ | allowed
^ C# 5 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[covariant and contravariant generics](https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance) | ✔️ | ✔️ | encouraged
[default arguments](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments) | ✔️ | ✔️ | preferred over overloads
[named arguments](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#named-arguments) | ✔️ | ✔️ | encouraged for primitive-typed parameters
[`dynamic` type](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic) | ✔️ | ⭕ | discouraged
^ C# 4 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[object initialisation syntax](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers) | ✔️ | ✔️ | encouraged
[partial methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-method) | ✔️ | ✔️ | allowed
[`var`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var) | ✔️ | ✔️ | encouraged
[extension methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) | ✔️ | ✔️ | preferred over the same static method w/o `this` param
[`Expression` trees](https://docs.microsoft.com/en-us/dotnet/csharp/expression-trees) | ✔️ | ✔️ | discouraged (what are these even for)
[lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions) | ✔️ | ✔️ | encouraged
LINQ's [query expression syntax](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/query-expression-syntax-for-standard-query-operators) | ✔️ | ✔️ | disallowed
[anonymous types](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/anonymous-types) | ✔️ | ✔️ | disallowed (use tuples)
[auto-props](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties) | ✔️ | ✔️ | encouraged
^ C# 3 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`using` alias](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#using-alias) | ✔️ | ✔️ | discouraged unless there's a conflict
[`unsafe`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code) (pointers etc.) | ✔️ | ✔️ | discouraged