Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

C# 8 in Libraries and Applications - BASTA! Frankfurt 2020

82 views

Published on

C# 8 with nullable reference types, default interface members, ranges and indices, async streams, using declaration, and switch expression.
Source code: https://github.com/christiannagel/bastafrankfurt2020

Published in: Software
  • Be the first to comment

  • Be the first to like this

C# 8 in Libraries and Applications - BASTA! Frankfurt 2020

  1. 1. C# 8 in Libraries and Applications Christian Nagel https://csharp.christiannagel.com
  2. 2. Topics New C# 8 Features Moving from existing code Guidelines
  3. 3. Christian Nagel • Training • Coaching • Consulting • Development • Microsoft MVP • www.cninnovation.com • csharp.christiannagel.com • github.com/cninnovation
  4. 4. How to use C# 8
  5. 5. How to use C# 8 • By default enabled with .NET Core 3.0 and .NET Standard 2.1 • Enable with other projects: <LangVersion> • Directory.Build.Props File
  6. 6. Features based on Frameworks/Runtimes • Syntax sugar features with all frameworks • Some features need specific classes & interfaces • Ranges, async streams • Runtime updates required • .NET Standard 2.1 • Default Interface Members
  7. 7. Nullable Reference Types
  8. 8. Null References • Billion Doller Mistake • 1965 in Algol by Sir Tony Hoare • Most common .NET Exception • NullReferenceException
  9. 9. Null Conditional Operator (C# 6) • Null checks made easier int? length = customers?.Length; Customer first = customers?[0]; int? count = customers?[0]?.Orders?.Count(); public void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  10. 10. Coalescing Operator (C# 5) • Default values for null int length = customers?.Length ?? 0; public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
  11. 11. Reference Types are not Nullable (C# 8) • #nullable enable/disable/restore • annotated with ? – nullable reference type • string? • Null-forgiving operator • ! • Null-coalescing assignment • numbers ??= new List<string>();
  12. 12. Features - Nullable Reference Types • Documentation: null or not null • Helps finding bugs, not a guarantee! • 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
  13. 13. Demo • Nullable Reference Types • Enable nullability • Add annotations • Solving issues • Current issues
  14. 14. Guidelines • Library authors – Nullable adoption phase up to .NET 5 • App developers – nullability on your own pace • Annotate new APIs • Do not remove argument validation • Parameter is non-nullable if parameters are checked (ArgumentNullException) • Parameter is nullable if documented to accept null • Prefer nullable over non-nullable with disagreements
  15. 15. Default Interface Members
  16. 16. Default Interface Members - Overview • Interfaces with implementation • Modifiers: private, protected, internal, public, virtual, abstract, override, sealed, static, extern
  17. 17. Default Interface Methods Changing of interfaces without breaking changes 1 Traits – Reuse implementations in independent types 2 Based on Java's Default Methods 3
  18. 18. Default Interface Methods • Changing the interface without breaking changes public interface ILogger { void Log(string message); } public interface Ilogger { void Log(string message); void Log(Exception ex) => Log(ex.Message); } public class MyLogger : ILogger { public void Log(string message) => Console.WriteLine(message); }
  19. 19. Tipps Is the first version of the interface complete? Additions are now possible! Alternative to extension methods Runtime extensions needed!
  20. 20. Indices and Ranges
  21. 21. Indexes and Ranges Index und Range & Types & Extensions New Operators • ^ Hat Operator • .. Range Operator
  22. 22. Hat Operator int[] arr = { 1, 2, 3 }; int lastItem = arr[^1];
  23. 23. Range string text1 = "the quick brown fox jumped over the lazy dogs"; string quick = text1[4..9]; string dog = text1[^4..^1]; string brownfoxjumpedandmore = text1[10..]; string thequick = text1[..8]; string text2 = text1[..];
  24. 24. Demo • Ranges and Indices • Access Slice of Span<T> • Access String • Range, Index Types • Custom Collections
  25. 25. Implicit Support • countable (Length, Count) • instance indexer with int Index • countable • Slice method with two int Range
  26. 26. Async Streams
  27. 27. Async Streams Async before: async/await returns one result Async streams extends async/await with a stream of results Async sources controlled by the consumer Alternative to System.Reactive
  28. 28. Async Streams • IAsyncDisposable • IAsyncEnumerable • IAsyncEnumerator public interface IAsyncDisposable { ValueTask DisposeAsync(); } public interface IAsyncEnumerable<out T> { IAsyncEnumerator<T> GetAsyncEnumerator(); } public interface IAsyncEnumerator<out T> : IAsyncDisposable { ValueTask<bool> MoveNextAsync(); T Current { get; } }
  29. 29. Using Async Streams • await foreach IAsyncEnumerator<T> enumerator = enumerable.GetAsyncEnumerator(); try { while (await enumerator.MoveNextAsync()) { Use(enumerator.Current); } } finally { await enumerator.DisposeAsync(); } await foreach (var i in enumerable) { Use(i); }
  30. 30. 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"); } }
  31. 31. Demo • Async Streams & SignalR • Streaming from the Server to the Client • Streaming from the Client to the Server • C# 8 Async Streams
  32. 32. More Features…
  33. 33. using declaration public void Method(IEnumerable<string> lines) { using var file = new StreamWriter("sample.txt"); foreach (var line in lines) { file.WriteLine(line); } }
  34. 34. 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" } };
  35. 35. 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" };
  36. 36. Demo • Switch expressions with tuples • Switch with pattern matching
  37. 37. Summary Avoid Errors Better Productivity Better Performance
  38. 38. Questions?
  39. 39. For action Annotate libraries with nullability Use new C# 8 features https://csharp.christiannagel.com https://github.com/christiannagel https://github.com/ProfessionalCSharp
  40. 40. Thank you!

×