c# 6.0 - dotnetnotts
TRANSCRIPT
C# 6.0 Features and Tooling
Matt Ellis@citizenmatt
Back storyRoslynLanguage features
HISTORY
C# 1.0 (2002)
Initial commit
C# 1.2 (2003)Really!?
C# 2.0 (2005)
GenericsNullable types
IteratorsPartial typesAnonymous methodsGetter/setter accessibilityStatic classes
New CLR features
Language features
C# 3.0 (2007)
Anonymous typesImplicit typing (“var”)Extension methodsLambda expressionsQuery expressionsExpression trees
Auto propertiesObject and collection initialisersPartial methods
LINQ
C# 4.0 (2010)
DynamicNamed and optionalparametersEmbedded interop types
Co- and contra-variance for generics
COM interop
C# 5.0 (2012)
Async/awaitCaller Info attributes
private async static Task<string> DownloadText(string url){ using (var webClient = new WebClient()) return await webClient.DownloadStringTaskAsync(url);}
C# 6.0 (2015)
Roslyn
Auto property initialisersIndex initialisersUsing static membersNull propagationExpression bodied membersIEnumerable paramsnameof operator
Await in catch/finallyException filters
Ceremony
New compiler!
ROSLYN
Roslyn
“.NET Compiler Platform”Complete redesign & rewrite of compilerC# vs C++Decade old codebaseEase of adding new featuresParallel compilationOpen Source (github.com/dotnet/roslyn)
Compiler as a service
Compiler exposed as an APICan host compiler in-processCan compile in-memoryCan affect compilation steps, e.g. resolving references (but no meta-programming)Can access parse trees and semantic model
IDE features
Compiler powers syntax highlighting, navigation, etc.Parser and semantic model available across the IDEAbstract Syntax Tree based analysis, navigation and refactoring
ScriptCS
C# based REPL and scriptingScript packs and NuGet references
ASP.Net vNext
Compiler pipeline based on Roslyn
Compiles to in-memory assemblies
Edit file + refresh browser = compiled
No need to recompile whole project
New project system, based on NuGet
Controls assembly/package resolution
Meta-programming. Kinda.
Problem:
CLR types defined by assembly qualified nameEverything based on binary referencesContracts are hardcoded. No loose coupling
E.g.: want to use the same logger across application + 3rd party framework?Must share contract (assembly), or provide adapters
Assembly neutral interfaces
Ideal:
Duck typing/structural equivalenceCommon contracts defined in source, resolved at runtime
But how do you work around assembly qualified name?
Compile time// Compiled to CommonLogging.ILogger.dllnamespace CommonLogging{ [AssemblyNeutral] public interface ILogger { void Log(string value); }}
Finds and removes [AssemblyNeutral] contract typesCompile a new assembly for each typePredictable assembly qualified nameOriginal assembly references the types in new assembliesNew assemblies saved as embedded resources in original assemblyMultiple assemblies defining same types generate same assemblies
Run time
Application tries to resolve neutral assembly
Host environment looks in resources of all assemblies
Uses first match it finds
If multiple assemblies define same type, same dll is generated
Types with same namespace and name “Just Work”
LANGUAGE FEATURES
Language features
Auto property initialisersIndex initialisersUsing static membersNull propagationExpression bodied membersIEnumerable paramsnameof operatorAwait in catch/finallyException filters
Auto property initialisation
Proper readonly (immutable) auto properties – getter onlyNo need for constructor or backing field
public class Person{ public string Name { get; } public Address Address { get; } = new Address();
public Person(string name) { // Assignment to getter only properties Name = name; }}
Index initialisers
Nicer syntax than previous collection initialisersCalls indexer rather than Add methodExtends object initialiser
var d = new Dictionary<string, int>{ ["doodad"] = 42, ["widget"] = 64};
Using static membersUse static members without qualificationApplies to methods, properties, fields, events, etc.Does not apply to extension methodsLocal declarations resolved first
using static System.Math;public class Sphere{ private readonly double radius;
public Sphere(double radius) { this.radius = radius; }
public double Volume { get { return (3/4)*PI*Pow(radius, 3); } }}
nameof operator
Returns short name of symbolAny symbol – class, class member, namespace, type parameters, variables, etc.Ambiguities are not an error
public void Foo(string value){ if (value == null) throw new ArgumentNullException(nameof(value));}
Expression bodied members
Replaces single line methods, properties, indexers, operators, etc.
Familiar lambda arrow syntax
Properties are created as getter only
Can only be single expression
public string FullName => FirstName + " " + LastName;
Null propagation
Conditional access operatorReturns null if qualifier is null, else evaluatesShort circuitingConditional method invocation, indexer accessLeft hand side evaluated only once – thread safe
int? length = customers?.Length;int length2 = customers?.Length ?? 0;
Await in catch/finally
Implementation detailPreviously “impossible”IL cannot branch into or out of catch/finallyUses ExceptionDispatchInfo to save exception state and rethrow if necessary
Exception filters
Existing CLR featureOnly run catch block if exception handler returns trueReplaces if () throw; patternExpected “abuse” – logging
catch (Exception e) when (Log(e)){ // ...}
private bool Log(Exception exception){ Debug.WriteLine(exception); return false;}
String interpolation
$"My name is {name} and I’m {person.Age} years old"
Compiles to string.FormatHoles can contain expressions – e.g. $"Hi {GetName(person)}"Uses current culture by defaultFormat specifiers – e.g. $"{foo:D}”Does not work with stored resource stringsVerbatim strings can contain strings. What!?
Formattable strings
Interpolated strings converted to FormattableString by FormattableStringFactory.CreatePassed to method that returns a string formatted as required, e.g. Invariant culture, URL encoding, SQLProvide own FormattableString implementations on downlevel versions
Summary
RoslynComplete rewriteEasier to maintainOpen SourceCompiler as a service
IDE features, scripting, hosting compilers
Language featuresAuto property initialisersGetter only auto propertiesIndex initialisersUsing static membersNull propagationExpression bodied membersnameof operatorAwait in catch/finallyException filters
Bonus – C# 7.0
Strong interestTuplesPattern matchingRecordsNon-nullable typesAsync streams (observables) + disposable
Some interestCovariant return typesExpanded expression treesSyntax for lists + dictionariesDeterministic disposalImmutable typesType providersScriptingMethod contractsyield foreachparams IEnumerablemore...