Updated Available C# and .NET features (markdown)

James Groom 2024-03-29 09:56:48 +10:00
parent 44c6f835c8
commit c6aac381ed
1 changed files with 52 additions and 40 deletions

@ -10,9 +10,10 @@ Legend:
⭕ Available with polyfill ⭕ Available with polyfill
❌ Not available ❌ Not available
? Unknown ? Unknown
Some features are marked ✔️ despite ostensibly needing a polyfill because they are enhancements to existing features and work anywhere the base feature is available—for example, `switch`ing on a `Span<char>` requires no additional polyfill.
🔵 Availablity in .NET Framework 4.8 (`net48`) 🔵 Availability in .NET Framework 4.8 (`net48`)
🟢 Availablity in .NET Standard 2.0 (`netstandard2.0`) 🟢 Availability in .NET Standard 2.0 (`netstandard2.0`)
I have not considered Framework 4.7.2 and below as there is little reason not to upgrade to Framework 4.8. I have not considered Framework 4.7.2 and below as there is little reason not to upgrade to Framework 4.8.
I have not considered Framework 4.8.1 because it matches Framework 4.8 in terms of language features and is generally not useful. I have not considered Framework 4.8.1 because it matches Framework 4.8 in terms of language features and is generally not useful.
I use Standard 2.0 and not Standard 2.1 as the latter is not subsumed by Framework 4.8, rendering it useless. I use Standard 2.0 and not Standard 2.1 as the latter is not subsumed by Framework 4.8, rendering it useless.
@ -21,50 +22,61 @@ I use Standard 2.0 and not Standard 2.1 as the latter is not subsumed by Framewo
Feature | 🔵 `net48` | 🟢 `ns2.0` | convention for main BizHawk solution 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 [`[InlineArray]`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#inline-arrays) | ❌ | ❌ | 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 [`using` aliases](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#using-alias) for tuples, etc. | ✔️ | ✔️ | disallowed (use a struct instead of a tuple alias and we'll consider replacing them with `<Using/>` later)
Kotlin-like [raw string literals](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#raw-string-literals) | ? | ? | unsupported [default arguments for lambdas](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#input-parameters-of-a-lambda-expression) | ✔️ | ✔️ | encouraged
[list pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#list-patterns) | ? | ? | unsupported [`ref readonly` parameters](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/method-parameters#ref-readonly-modifier) | ✔️ | ✔️ | allowed
[multi-line expressions in interpolated strings](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#newlines-in-string-interpolations) | ? | ? | unsupported [unified `Span`/`Array`/`List` init syntax](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions) | ✔️ | ✔️ | encouraged
[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 [primary constructors](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors) on non-`record`s | ✔️ | ✔️ | encouraged
[genericised attributes](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-attributes) | ? | ? | unsupported ^ C# 12 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`file` access modifier](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/file) | ✔️ | ✔️ | allowed
simple [`ref` fields](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct#ref-fields) | ❌ | ❌ | unsupported
[`required` props](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required) | ⭕ | ⭕ | disallowed
[`Encoding.UTF8.GetBytes` shorthand](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#utf-8-string-literals) | ✔️ | ✔️ | encouraged
[enhanced `nameof`](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#extended-nameof-scope) | ✔️ | ✔️ | encouraged
[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) | ✔️ | ✔️ | encouraged
Kotlin-like [raw string literals](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#raw-string-literals) | ✔️ | ✔️ | allowed
[list pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#list-patterns) | ✔️ | ✔️ | encouraged
[multi-line expressions in interpolated strings](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#newlines-in-string-interpolations) | ✔️ | ✔️ | discouraged
[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) | ✔️ | ✔️ | allowed
^ C# 11 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ C# 11 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
per-method [`AsyncMethodBuilder`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#asyncmethodbuilder-attribute) | ? | ? | unsupported 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 `null` analysis](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#improved-definite-assignment) | ✔️ | ✔️ | allowed
[enhanced destructuring](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#assignment-and-declaration-in-same-deconstruction) | ✔️ | ✔️ | unsupported [enhanced destructuring](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#assignment-and-declaration-in-same-deconstruction) | ✔️ | ✔️ | encouraged
[`sealed` `ToString` in records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#built-in-formatting-for-display) | ? | ? | unsupported [`sealed` `ToString` in records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#built-in-formatting-for-display) | ✔️ | ✔️ | discouraged (as per records)
limited string interpolation in [consts](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const) | ✔️ | ✔️ | unsupported limited string interpolation in [consts](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const) | ✔️ | ✔️ | encouraged
[attributes for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#attributes) | ✔️ | ✔️ | unsupported [attributes for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#attributes) | ✔️ | ✔️ | allowed
[type inference for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#natural-type-of-a-lambda-expression) | ✔️ | ✔️ | unsupported [type inference for lambdas](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions#natural-type-of-a-lambda-expression) | ✔️ | ✔️ | allowed
[pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern) IV | ✔️ | ✔️ | unsupported [pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern) IV | ✔️ | ✔️ | encouraged
[`namespace A;`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace) | ✔️ | ✔️ | unsupported [`namespace A;`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace) | ✔️ | ✔️ | disallowed (will mass-migrate)
[`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 [`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) | ✔️ | ✔️ | disallowed (will mass-migrate)
[custom interpolated string handlers](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler) | ? | ? | unsupported [custom interpolated string handlers](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler) | ⭕ | ⭕ | allowed
[`with` for structs](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | unsupported [`with` for structs](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | allowed
[enhanced struct field init](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#struct-initialization-and-default-values) | ✔️ | ✔️ | unsupported [enhanced struct field init](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#struct-initialization-and-default-values) | ✔️ | ✔️ | discouraged
[`record struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) | ✔️ | ✔️ | unsupported [`record struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) | ✔️ | ✔️ | discouraged (as per records)
^ C# 10 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ C# 10 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
enhanced [partial methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-method) | ? | ? | unsupported enhanced [partial methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-method) | ✔️ | ✔️ | allowed
[`[ModuleInitializer]` method](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#moduleinitializer-attribute) | ⭕ | ⭕ | unsupported [`[ModuleInitializer]` method](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#moduleinitializer-attribute) | ⭕ | ⭕ | discouraged
[attributes on local methods](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/local-function-attributes) | ✔️ | ✔️ | allowed [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 [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) [`foreach` picks up extension `GetEnumerator`s](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 [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 [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 [`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 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 basic [function pointers](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers) | ✔️ | ✔️ | encouraged
[`nint`/`nuint`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#native-sized-integers) | ✔️ | ✔️ | allowed [`nint`/`nuint` keywords](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 [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) [unindented `Main`](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements) | ✔️ | N/A | N/A (neither executable uses it)
[`with` for records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | discouraged [`with` for records](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression) | ✔️ | ✔️ | discouraged (as per records)
[`init`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init) | ✔️ | ✔️ | 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 [`record class`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) | ✔️ | ✔️ | discouraged
^ C# 9 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ C# 9 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
`@$""` (instead of `$@""`) | ✔️ | ✔️ | disallowed `@$""` (instead of `$@""`) | ✔️ | ✔️ | disallowed
[`stackalloc`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc) as arg for `Span` param | ✔️ | ✔️ | allowed [`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 [`??=`](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 `..`) [`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: unmanaged, IComparable<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 [async streams](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream) | ⭕ | ⭕ | unknown
NRTs (attribute-based analysis) | ⭕ | ⭕ | encouraged 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 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
@ -78,19 +90,19 @@ static [local methods](https://docs.microsoft.com/en-us/dotnet/csharp/programmin
`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) `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 [`stackalloc`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc) with array intialiser | ✔️ | ✔️ | encouraged
^ C# 7.3 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ C# 7.3 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`Span`](https://docs.microsoft.com/en-us/dotnet/standard/memory-and-spans/) and co. | ⭕ | ⭕ | allowed [`Span`](https://docs.microsoft.com/en-us/dotnet/standard/memory-and-spans/) and co. | ⭕ | ⭕ | encouraged
[`ref struct`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#ref-struct) (stack-bound) | ✔️ | ✔️ | allowed [`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 [`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` | --- ^ 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 [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 [`default` without type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/default#default-literal) | ✔️ | ✔️ | encouraged for non-nullable value types, or as `default!` to appease compiler when definitely assigned, 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) [`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` | --- ^ C# 7.1 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[`throw` expression](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/throw#the-throw-expression) | ✔️ | ✔️ | encouraged [`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 [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 [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 [`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 [expression-bodied constructors](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) | ✔️ | ✔️ | preferred over lambdas/delegates if used multiple times or to unsub from event [local methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions) | ✔️ | ✔️ | preferred over lambdas/delegates if used multiple times or to unsub from event
basic [pattern matching](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching) | ✔️ | ✔️ | 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 [`KeyValuePair<K, V>.Deconstruct`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair-2.deconstruct?view=net-6.0) | ⭕ | ⭕ | allowed
@ -110,11 +122,11 @@ inline initialisation of [auto-props](https://docs.microsoft.com/en-us/dotnet/cs
^ C# 5 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ C# 5 ^ | 🔵 `net48` | 🟢 `ns2.0` | ---
[covariant and contravariant generics](https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance) | ✔️ | ✔️ | encouraged [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 [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 [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 or when 2+ parameters are of the same type
[`dynamic` type](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic) | ✔️ | ⭕ | discouraged [`dynamic` type](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic) | ✔️ | ⭕ | discouraged
^ C# 4 ^ | 🔵 `net48` | 🟢 `ns2.0` | --- ^ 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 [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 simple [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) | ✔️ | ✔️ | preferred except when target-typed `new()` can be used [`var`](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var) | ✔️ | ✔️ | preferred except when target-typed `new()` can be used
[extension methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) | ✔️ | ✔️ | allowed [extension methods](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) | ✔️ | ✔️ | allowed
[`Expression` trees](https://docs.microsoft.com/en-us/dotnet/csharp/expression-trees) | ✔️ | ✔️ | discouraged (what are these even for) [`Expression` trees](https://docs.microsoft.com/en-us/dotnet/csharp/expression-trees) | ✔️ | ✔️ | discouraged (what are these even for)