15. Tuples
• Werte unterschiedlicher Typen kombinieren
• Strong Names
• Value Types var t1 = (n: 42, s: "magic");
int i1 = t1.n;
string s1 = t1.s;
16. Deconstruction
• Create parts from objects or tuples
• Implement method Deconstruct
var p1 = new Person("Tom", "Turbo");
(string firstName, string lastName) = p1;
17. Pattern Matching (C# 7.0)
• is Operator and switch statement extended
• Const Pattern
• Type Pattern
• Var Pattern
public void IsSample(object o)
{
if (o is 42)
{
}
if (o is Person p)
{
}
if (o is var v1)
{
}
}
public void PatternMatchingWithSwitchStatement(object o)
{
switch (o)
{
case 42:
break;
case Person p when p.FirstName == "Katharina":
break;
case Person p:
break;
case var v:
break;
}
}
18. C# 7.1
• Async main
• Generics pattern match
• Infer tuple names
• Target typed default
static async Task Main()
{
await FooAsync();
}
public void Send<T>(T packet)
where T : Packet
{
if (packet is KeepalivePacket keepalive)
{
}
var t1 = (racer.FirstName, racer.Wins);
int wins = t1.Wins;
ImmutableArray<int> arr = default(ImmutableArray<int>);ImmutableArray<int> arr = default;
19. C# 7.2
• Leading Separator
• Non-trailing named arguments
• private protected
• Conditional Ref
• readonly ref
• Span Safety
ushort b1 = 0b_1010_1111_0101_0000;
if (Enum.TryParse(day, ignoreCase: true,
out DayOfWeek weekday))
{
reservation.Weekday = weekday;
}
20. C# 7.3
• Auto Property Field Attributes
• Generic constraints
• unmanaged, Enum, Delegate
• Expression Variables in Initializers
• Pattern-based fixed statement
• Ref local reassignment
• Stackalloc array initializers
[Serializable]
public class Foo
{
[field: NonSerialized]
public string MySecret { get; set; }
}
void Hash<T>(T value) where T : unmanaged
{
}
var d1 = stackalloc int[3] { 1, 2, 3 };
var d2 = stackalloc int[] { 1, 2, 3 };
var d3 = stackalloc[] { 1, 2, 3 };
21. C# 7 Point Releases
• Sicherer, effizienter Code
• Mehr Freiheiten
• Weniger Code
33. Async Streams
• async/await liefert ein Ergebnis
• Async Streams erweitert async/await mit
Stream von Ergebnissen
• Asynchronous Datenquellen die vom Consumer
kontrolliert werden
• Alternative zu System.Reactive
34. Async Streams
• IAsyncDisposable
• IAsyncEnumerable
• IAsyncEnumerator
public interface IAsyncDisposable
{
Task DisposeAsync();
}
public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator();
}
public interface IAsyncEnumerator<out T> :
IAsyncDiposable
{
Task<bool> MoveNextAsync();
T Current { get; }
}
35. Using Async Streams
• foreach await
IAsyncEnumerator<T> enumerator =
enumerable.GetAsyncEnumerator();
try
{
while (await enumerator.MoveNextAsync())
{
Use(enumerator.Current);
}
}
finally
{
await enumerator.DisposeAsync();
}
foreach await (var i in enumerable)
{
Use(i);
}
36. Async with yield
• return IAsyncEnumerable static async IAsyncEnumerable<int> MyIterator()
{
try
{
for (int i = 0; i < 100; i++)
{
await Task.Delay(1000);
yield return i;
}
}
finally
{
await Task.Delay(200);
Console.WriteLine("finally");
}
}
37. Async Streams
Open
Questions
• LINQ
• ~600 neue Methoden
wären erfoderlich
• Interactive Extensions (Ix)
implementiert viele
• => Support Community
extend Ix
• Integration mit IObservable<T>
• Integration auf Library-
Ebene
40. Record Implementation
• Implements
• IEquatable
• GetHashCode
• Deconstruct
• With
public struct Pair(object First, object Second);
public struct Pair : IEquatable<Pair>
{
public object First { get; }
public object Second { get; }
public Pair(object First, object Second)
{
this.First = First;
this.Second = Second;
}
public bool Equals(Pair other) =>
Equals(First, other.First) && Equals(Second, other.Second);
public override bool Equals(object other) =>
(other as Pair)?.Equals(this) == true;
public override int GetHashCode() =>
(First?.GetHashCode()*17 + Second?.GetHashCode()).GetValueOrDefault();
public Pair With(object First = this.First, object Second = this.Second) =>
new Pair(First, Second);
public void Deconstruct(out object First, out object Second)
{
First = this.First;
Second = this.Second;
}
}
var p1 = new Pair("one", "two");
var p2 = p1.With(First: "alpha");
41. Caller-Receiver Parameter
class Point
{
public readonly int X;
public readonly int Y;
public Point With(int x = this.X, int y = this.Y) =>
new Point(x, y);
//...
}
var p = new Point(3, 4);
p = p.With(x: 1);
45. Slice
string text1 = "the quick brown fox jumped over the lazy dogs";
string text2 = text1[4..8];
string text3 = text1[^4..^1];
string text4 = text1[10..];
string text5 = text1[..8];
string text6 = text1[..];
46. More Uses
• switch, foreach
switch (codePoint)
{
case 1536..1541:
break;
foreach (var item in 3..5)
{
47. Patterns
Extended
• Always match
Discard Pattern
• Match für Property Werte
Property Pattern
• Match für innere Properties
Recursive Pattern
• Moderner switch Syntax
switch Expression
48. Pattern Matching Now
static string M1(Shape shape)
{
switch (shape)
{
case Shape s when s.Size.height > 100:
return $"large shape with size {s.Size} at position {s.Position}";
case Ellipse e:
return $"Ellipse with size {e.Size} at position {e.Position}";
case Rectangle r:
return $"Rectangle with size {r.Size} at position {r.Position}";
default:
return "another shape";
}
}
49. switch Expression
static string M2(Shape shape) =>
shape switch
{
Shape s when s.Size.height > 100 =>
$"large shape with size {s.Size} at position {s.Position}",
Ellipse e =>
$"Ellipse with size {e.Size} at position {e.Position}",
Rectangle r =>
$"Rectangle with size {r.Size} at position {r.Position}",
_ => "another shape"
}
};
50. Recursive, Property, and Discard Patterns
static string M3(Shape shape) =>
shape switch
{
CombinedShape (var shape1, var (pos, _)) =>
$"combined shape - shape1: {shape1.Name}, pos of shape2: {pos}",
{ Size: (200, 200), Position: var pos } =>
$"shape with size 200x200 at position {pos.x}:{pos.y}",
Ellipse (var pos, var size) =>
$"Ellipse with size {size} at position {pos}",
Rectangle (_, var size) => $"Rectangle with size {size}",
_ => "another shape"
};
51. Null
References
Most common .NET Exception
NullReferenceException
Billion Dollar Mistake
1965 in Algol
by Tony Hoare
"Billion Dollar
Mistake"
53. Coalescing Operator (C# 5)
• Default values for null
int length = customers?.Length ?? 0;
public bool CanExecute(object parameter) =>
_canExecute?.Invoke() ?? true;
54. Nullable
Reference
Types
• Hilft finden von Bugs,
aber keine Garantie!
• Flow analysis - tracks nullable
reference variables
• Breaks existing code (opt-in)
• Nullability implemented with
metadata (ignored by downlevel
compilers)
• string, T non-nullable
• string?, T? nullable
55. Declare Nullable Reference Types
• Default to non-nullable
• ? to make reference type nullable
class Book
{
public Book(string title, string? isbn = null)
{
Title = title;
Isbn = isbn;
}
public string Title; // not null
public string? Isbn; // may be null
}
56. Using nullable reference type
void M1(string? ns)
{
Console.WriteLine(ns.Length); // compiler warning
void M2(string? ns)
{
if (ns == null) throw new ArgumentNullException(nameof(ns));
Console.WriteLine(ns.Length); // ok, not null
ns = null;
Console.WriteLine(ns.Length); // compiler warning
void M3(string? ns)
{
if (ns != null)
{
Console.WriteLine(ns.Length); // ok
57. Using non-nullable reference type
void M1(string ns)
{
Console.WriteLine(ns.Length); // ok
void M2(Book b)
{
b.Title = null; // warning
string isbn = b.Isbn; // warning – may be null
string title = b.Title; // ok
58. Compatibility
• Enable this in your own speed
// Enable assembly-level
[module: NonNullTypes]
[NonNullTypes(false)]
public class Foo
{
}
61. What's next –
Try it out!
• https://github.com/dotnet/csharplang/wiki/Nullable-
Reference-Types-Preview
• Visual Studio 2017 15.5-15.8 (funktioniert nicht mit
15.8.4, 15.8.5)
Nullable Reference Types
• https://github.com/dotnet/csharplang/wiki/vNext-
Preview
• Visual Studio 2017 15.5-15.7
Patterns und Ranges
• https://github.com/dotnet/roslyn
Andere Features