From 179fcaa4cd234314d5fbbe6e56a0af016feee996 Mon Sep 17 00:00:00 2001 From: James Groom Date: Fri, 8 Jul 2022 03:30:05 +1000 Subject: [PATCH] Created Available C#/.NET features (markdown) --- Available-C#-.NET-features.md | 125 ++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 Available-C#-.NET-features.md diff --git a/Available-C#-.NET-features.md b/Available-C#-.NET-features.md new file mode 100644 index 0000000..49fb821 --- /dev/null +++ b/Available-C#-.NET-features.md @@ -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`](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)/[``](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` 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.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 \ No newline at end of file