-
Notifications
You must be signed in to change notification settings - Fork 430
Available C# and .NET features
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 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'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.
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: .NET calls destructuring "deconstructing", not to be confused with destructing which .NET calls "finalising".
| Feature | 🔵 net48
|
🟢 ns2.0
|
convention for main BizHawk solution |
|---|---|---|---|
enhanced nameof |
? | ? | unsupported |
pattern matching for Span<char> |
? | ? | unsupported |
| Kotlin-like raw string literals | ? | ? | unsupported |
| list pattern matching | ? | ? | unsupported |
| multi-line expressions in interpolated strings | ? | ? | unsupported |
| generic maths using static abstract members | ? | ? | unsupported |
| genericised attributes | ? | ? | unsupported |
| ^ C# 11 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
per-method AsyncMethodBuilder
|
? | ? | unsupported |
enhanced null analysis |
? | ? | unsupported |
| enhanced destructuring | ✔️ | ✔️ | unsupported |
sealed ToString in records |
? | ? | unsupported |
| limited string interpolation in consts | ✔️ | ✔️ | unsupported |
| attributes for lambdas | ✔️ | ✔️ | unsupported |
| type inference for lambdas | ✔️ | ✔️ | unsupported |
| pattern matching IV | ✔️ | ✔️ | unsupported |
namespace A; |
✔️ | ✔️ | unsupported |
global using A;/<Using>
|
✔️ | ✔️ | unsupported |
| custom interpolated string handlers | ? | ? | unsupported |
with for structs |
✔️ | ✔️ | unsupported |
| enhanced struct field init | ✔️ | ✔️ | unsupported |
record struct |
✔️ | ✔️ | unsupported |
| ^ C# 10 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
| enhanced partial methods | ? | ? | unsupported |
[ModuleInitializer] method |
⭕ | ⭕ | unsupported |
| attributes on local methods | ✔️ | ✔️ | allowed |
| discarding lambda parameters | ✔️ | ✔️ | encouraged |
foreach picks up GetEnumerator extension |
✔️ | ✔️ | discouraged (surely this can only be used for stupid) |
| covariant return type when overriding | ❌ | ❌ | unsupported |
| enhanced type inference | ✔️ | ✔️ | omit explicit type cast where possible, otherwise place the cast on default branch of switch and first branch of ternary |
static lambdas |
✔️ | ✔️ | encouraged |
target-typed new()
|
✔️ | ✔️ | encouraged |
| function pointers | ? | ? | unsupported |
nint/nuint |
✔️ | ✔️ | allowed |
| pattern matching III | ✔️ | ✔️ | encouraged |
unindented Main |
? | ? | N/A (neither executable uses it) |
with for records |
✔️ | ✔️ | discouraged |
init |
✔️ | ✔️ | discouraged |
record class |
✔️ | ✔️ | discouraged |
| ^ C# 9 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
@$"" (instead of $@"") |
✔️ | ✔️ | disallowed |
stackalloc as arg for Span param |
✔️ | ✔️ | allowed |
??= |
✔️ | ✔️ | encouraged |
Index and Range (^ and .. operators) |
⭕ | ⭕ | unsupported (we have a generic Range<T> but it has some problems, like not working with ..) |
| async streams | ⭕ | ⭕ | unknown |
| NRTs (attribute-based analysis) | ⭕ | ⭕ | encouraged |
| NRTs (syntax and basic analysis) | ✔️ | ✔️ | encouraged for new files, see project graph for when #nullable enable is needed |
| static local methods | ✔️ | ✔️ | encouraged |
using statement without block |
✔️ | ✔️ | encouraged |
| pattern matching II | ✔️ | ✔️ | encouraged |
switch expression |
✔️ | ✔️ | encouraged |
| default interface methods | ❌ | ❌ | unsupported |
readonly methods/getters/setters |
✔️ | ✔️ | encouraged |
| ^ C# 8 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
field attribute target for auto-prop backing field |
✔️ | ✔️ | discouraged (surely this can only be used for stupid) |
stackalloc with array intialiser |
✔️ | ✔️ | encouraged |
| ^ C# 7.3 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
ref struct (stack-bound) |
✔️ | ✔️ | allowed |
readonly struct and in parameters |
✔️ | ✔️ | encouraged |
| ^ C# 7.2 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
| inferred tuple field names | ✔️ | ✔️ | discouraged |
default without type |
✔️ | ✔️ | encouraged for non-nullable value types, discouraged otherwise |
async Main |
? | ? | N/A (neither executable uses it) |
| ^ C# 7.1 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
throw expression |
✔️ | ✔️ | encouraged |
| enhanced int literals | ✔️ | ✔️ | encouraged |
| discards | ✔️ | ✔️ | encouraged |
ref returns/locals |
✔️ | ✔️ | allowed |
| expression-bodied ctors | ✔️ | ✔️ | encouraged |
| local methods | ✔️ | ✔️ | encouraged |
| basic pattern matching | ✔️ | ✔️ | encouraged |
KeyValuePair<K, V>.Deconstruct |
⭕ | ⭕ | allowed |
| basic tuples and destructuring | ✔️ | ✔️ | encouraged |
out var |
✔️ | ✔️ | encouraged |
| ^ C# 7.0 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
nameof |
✔️ | ✔️ | encouraged |
| interpolated string literals | ✔️ | ✔️ | preferred over string.Format or concatenation |
| null-conditional member access | ✔️ | ✔️ | required |
| expression-bodied methods/props | ✔️ | ✔️ | encouraged |
| inline initialisation of auto-props | ✔️ | ✔️ | encouraged |
catch (Exception e) when (predicate(e)) |
✔️ | ✔️ | encouraged |
using static A; |
✔️ | ✔️ | allowed only for the file's own namespace |
| ^ C# 6 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
[Caller*] |
✔️ | ✔️ | allowed |
async |
✔️ | ✔️ | allowed |
| ^ C# 5 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
| covariant and contravariant generics | ✔️ | ✔️ | encouraged |
| default arguments | ✔️ | ✔️ | preferred over overloads |
| named arguments | ✔️ | ✔️ | encouraged for primitive-typed parameters |
dynamic type |
✔️ | ⭕ | discouraged |
| ^ C# 4 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
| object initialisation syntax | ✔️ | ✔️ | encouraged |
| partial methods | ✔️ | ✔️ | allowed |
var |
✔️ | ✔️ | encouraged |
| extension methods | ✔️ | ✔️ | preferred over the same static method w/o this param |
Expression trees |
✔️ | ✔️ | discouraged (what are these even for) |
| lambdas | ✔️ | ✔️ | encouraged |
| LINQ's query expression syntax | ✔️ | ✔️ | disallowed |
| anonymous types | ✔️ | ✔️ | disallowed (use tuples) |
| auto-props | ✔️ | ✔️ | encouraged |
| ^ C# 3 ^ | 🔵 net48
|
🟢 ns2.0
|
--- |
using alias |
✔️ | ✔️ | discouraged unless there's a conflict |
unsafe (pointers etc.) |
✔️ | ✔️ | discouraged |
Seen something on this wiki page that can be improved? Only repo members can edit directly; please reach out on Discord or the TASVideos forums (and not this repo's issue tracker).