-
Notifications
You must be signed in to change notification settings - Fork 389
Available C# and .NET features
James Groom edited this page Jul 13, 2022
·
22 revisions
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 not to upgrade to Framework 4.8.
I use Standard 2.0 and not Standard 2.1 as the latter 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
|
--- |
Span and co. |
⭕ | ⭕ | allowed |
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 | ✔️ | ✔️ | preferred over lambdas/delegates if used multiple times or to unsub from event |
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 | ✔️ | ✔️ | preferred over delegates |
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 |