-
Notifications
You must be signed in to change notification settings - Fork 389
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 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 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 |
βοΈ | βοΈ | preferred except when target-typed new() can be used |
extension methods | βοΈ | βοΈ | allowed |
Expression trees |
βοΈ | βοΈ | discouraged (what are these even for) |
lambdas | βοΈ | βοΈ | preferred over delegates |
LINQ's query expression syntax | βοΈ | βοΈ | disallowed |
anonymous classes | βοΈ | βοΈ | disallowed (use tuples) |
auto-props | βοΈ | βοΈ | encouraged |
^ C# 3 ^ | π΅ net48
|
π’ ns2.0
|
--- |
anonymous delegates | βοΈ | βοΈ | disallowed |
^ C# 2 ^ | π΅ net48
|
π’ ns2.0
|
--- |
using alias |
βοΈ | βοΈ | discouraged unless there's a conflict |
delegate constructors | βοΈ | βοΈ | disallowed |
unsafe (pointers etc.) |
βοΈ | βοΈ | discouraged |