Skip to content

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