That Conference 2018, Kalahari Resort, Lake Delton, WI
What’s New in C#7 – Jason Bock
Day 2, 7 Aug 2018 4:00 PM
Disclaimer: This post contains my own thoughts and notes based on attending That Conference 2018 presentations. Some content maps directly to what was originally presented. Other content is paraphrased or represents my own thoughts and opinions and should not be construed as reflecting the opinion of the speakers.
Executive Summary
- Brief review of history of C# versions
- Lots of good new stuff in C# 7
- Importance of C# and .NET now being open source
Language Evolution
- C# – 2002, .NET 1.0
- v1 – classes, evenst, properties
- v2 – generics, partial types, anonymous methods, nullable types
- v3 – LINQ, implicit types, extension methods, lambda expressions
- v4 – dynamic binding, embedded interop types, named arguments
- v5 – async/await, caller info attributes
- v6 – Roslyn, exception filters, await in catch, auto prop initializer, default values for getters, expression-bodied members, string interpolation, null propagator, nameof
- v7 – out variables, tuples, local functions, binary literals, ref returns/locals, throw expressions
- v7.1
- v7.2
- v7.3
.NET Foundation
- Foster open source development
- Everything in .NET is now open source, on github
- Contributors from both inside/outside MIcrosoft
.csproj file
- Can target LangVersion, or latest
Binary digits, digit separators
- Underscore in integer constant is separator–doesn’t do anything
- Can do one or more underscores anywhere you like
- 0b – binary literals
Local functions
- Declare functions within functions
- Compiled as private methods, so performance is the same as private methods
Out var
- Replaces big try/catch block
- Or TryParse
- 3rd way in C# 7 – declare out var directly in method call
Ref Returns and Locals
- Copy semantics for structs
- Traditional list, indexer returns element, copied if element is value typed
- Indexer can use ref keyword to pass element back by reference
- For value typed objects, you get a reference to the value-typed object
- Far faster (if elements are large)
- Where you assign the element, you also use ref keyword
Pattern Matching
- Using switch statement
- Pass in parameter of parent type, then case on child type
- Can also add when clause to trigger on stuff specific to that subtype
- default case can be anywhere
- case null
Tuples
- Not Item1, Item2 syntax from v5
- Lets say that you want to pass two values back out of a function
- public (int, int) ReturnTwoInts() { … }
- Maps to ValueTuple, which has Item1, Item2, etc.
- Can do named values
- public (int x, int y) ReturnTwoInts
- Can now ref result.x, result.y
- Calling it
- (var x, var y) = ReturnTwoInts()
- Can use _ to indicate you don’t care
- Deconstruct method – pull data out as tuple (?)
- Can use tuples as concrete types in generics
- Assign multiple properties in a single line of code with a tuple
ValueTask<T>
- Task is a reference type, but you might want a value-typed task for performance
- ValueTask<T> is just a struct that does everything that a Task does
- You’d use this only if you really need the added performance
Expression bodied members
- Define wherever you like, not just read-only properties
[C# 7.1]
async main method
Default literals
- Instead of default(int), you can infer the type of the default
- So just use default keyword, type is inferred
[C# 7.2]
readonly struct
Spans
- Look at chunk of memory
- “Safe” way to read/write direct memory
- e.g. “11,22” .AsSpan()
- .Slice instead of Substring
- No allocations
- More performant
Constraint Generic
- To enum type, to delegate type
- where T : Enum
Compare Tuples
- Equality semantics is correct
Backing field not serialized
- On auto property, do [field: NonSerialized]
Future Directions
- Ranges – foreach, in 5..10
- Default Interface Methods – default implementation for a method on an interface
- Looks odd
- Nullable reference types
- Have to opt-in, to avoid breaks
- Once opt-in, MyClass mc would be non-nullable
- Have to do MyClass? to get nullable
- n!.Length – don’t worry about null-check
- async streams – async enumerator
- Generic attributes – e.g. [MyAttribute<int>]
- Records and with expressions
- Shapes and extensions
- Mads T
- Extensions everywhere – e.g. properties
Questions
Q: Isn’t this scary / dangerous? What is the main use case?
A: Multiple return values, e.g. int.Parse that is more elegant because it returns multiple things. Helps to avoid defining little objects designed just to pass data around between methods