Tuga IT 2017 - Whats new in C# 7

  • Published on
    18-Mar-2018

  • View
    245

  • Download
    1

DESCRIPTION

TUGA IT 2017 LISBON, PORTUGAL THANK YOU TO OUR SPONSORS PLATINUM GOLD SILVER PARTICIPATING COMMUNITIES CLOUD PRO PT Paulo Morgado • PauloMorgado.NET • @PauloMorgado •…

Transcript

TUGA IT 2017 LISBON, PORTUGAL THANK YOU TO OUR SPONSORS PLATINUM GOLD SILVER PARTICIPATING COMMUNITIES CLOUD PRO PT Paulo Morgado • PauloMorgado.NET • @PauloMorgado • github.com/paulomorgado • stackoverflow.com/users/402366/paulo-morgado • slideshare.net/PauloJorgeMorgado • docs.com/paulo-morgado/ • revista-programar.info/author/pmorgado/ • fca.pt/pt/catalogo- pesquisa/?filtros=2&pesquisa=Paulo+Morgado https://mvp.microsoft.com/en-us/PublicProfile/8656 https://mvp.microsoft.com/en-us/PublicProfile/8656 http://paulomorgado.net/ https://twitter.com/PauloMorgado https://github.com/paulomorgado https://stackoverflow.com/users/402366/paulo-morgado https://www.slideshare.net/PauloJorgeMorgado https://docs.com/paulo-morgado/ http://www.revista-programar.info/author/pmorgado/ https://www.fca.pt/pt/catalogo-pesquisa/?filtros=2&pesquisa=Paulo+Morgado http://www.vision-box.com/ http://www.vision-box.com/ Agenda • Literal improvements • More expression bodied members • Throw expressions • Out variables • Pattern matching • Tuples • Local functions • Ref returns and locals • Generalized async return types Literal improvements var n = 123456789;var n = 0x075BCD15; Binary Literals var n = 0b00000111010110111100110100010101; Digit Separators var d = 123_456_789; var x = 0x075B_CD15; var b = 0b0000_0111_0101_1011_1100_1101_0001_0101; 0b_0000_0111_0101_1011_1100_1101_0001_0101_; 0b0000__0111__0101__1011__1100__1101__0001__0101;   More expression bodied members class Person { private static ConcurrentDictionary names = new ConcurrentDictionary(); private int id = GetId(); public Person(string name) => names.TryAdd(id, name); // constructors ~Person() => names.TryRemove(id, out _); // destructors public string Name { get => names[id]; // getters set => names[id] = value; // setters } } Throw expressions class Person { public string Name { get; } public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name)); public string GetFirstName() { var parts = Name.Split(" "); return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!"); } public string GetLastName() => throw new NotImplementedException(); } Out variables public void PrintCoordinates(Point p) { int x, y; p.GetCoordinates(out x, out y); WriteLine($"({x}, {y})"); } public void PrintCoordinates(Point p) { p.GetCoordinates(out int x, out int y); WriteLine($"({x}, {y})"); } public void PrintCoordinates(Point p) { p.GetCoordinates(out var x, out var y); WriteLine($"({x}, {y})"); } Out variables - disacards public void PrintCoordinates(Point p) { p.GetCoordinates(out var x, out _); WriteLine($"{x}"); } Pattern matching public void PrintStars(object o) { if (o is null) return; // constant pattern "null" if (!(o is int i)) return; // type pattern "int i" WriteLine(new string('*', i)); } if (o is int i || (o is string s && int.TryParse(s, out i))) { /* use i */ } Pattern matching switch (shape) { case Ellipse e: WriteLine($"It's a {e.Height} x {e.Width} ellipse."); break; case Rectangle r: WriteLine($"{r.Height} x {r.Width} rectangle"); break; default: WriteLine(""); break; case null: throw new ArgumentNullException(nameof(shape)); } switch (shape) { case Ellipse c when c.Height == c.Width: WriteLine($"It's a {c.Height} circle."); break; case Ellipse e: WriteLine($"It's a {e.Height} x {e.Width} ellipse."); break; case Rectangle s when (s.Height == s.Width): WriteLine($"It's a {s.Height} square"); break; case Rectangle r: WriteLine($"It's a {r.Height} x {r.Width} rectangle"); break; default: WriteLine(""); break; case null: throw new ArgumentNullException(nameof(shape)); } Tuples Tuple LookupName(long id) // tuple return type { // retrieve first, middle and last from data storage return Tuple.Create(first, middle, last); // tuple value } var names = LookupName(id); WriteLine($"found {names.Item1} {names.Item3}."); (string, string, string) LookupName(long id) // tuple return type { // retrieve first, middle and last from data storage return (first, middle, last); // tuple literal } var names = LookupName(id); WriteLine($"found {names.Item1} {names.Item3}."); (string first, string middle, string last) LookupName(long id) // tuple return type { // retrieve first, middle and last from data storage return (first, middle, last); // tuple literal } var names = LookupName(id); WriteLine($"found {names.first} {names.last}."); Tuples // named tuple elements in a literal; var names = (first: first, middle: middle, last: last); WriteLine($"found {names.first} {names.last}."); Tuples - deconstruction (string first, string middle, string last) LookupName(long id) // deconstructing declaration (string first, string middle, string last) = LookupName(id); WriteLine($"found {first} {last}."); (string first, string middle, string last) LookupName(long id) // var inside (var first, var middle, var last) = LookupName(id); WriteLine($"found {first} {last}."); (string first, string middle, string last) LookupName(long id) // var outside var (first, middle, last) = LookupName(id); WriteLine($"found {first} {last}."); Tuple - deconstruction class Point { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } public void Deconstruct(out int x, out int y) { x = X; y = Y; } } (var myX, var myY) = GetPoint(); (var myX, _) = GetPoint(); // I only care about myX // calls Deconstruct(out myX, out myY); Tuples • Tuples are value types, and their elements are simply public, mutable fields. They have value equality, meaning that two tuples are equal (and have the same hash code) if all their elements are pairwise equal (and have the same hash code). • This makes tuples useful for many other situations beyond multiple return values. For instance, if you need a dictionary with multiple keys, use a tuple as your key and everything works out right. If you need a list with multiple values at each position, use a tuple, and searching the list etc. will work correctly. • Tuples rely on a family of underlying generic struct types called ValueTuple. If you target a Framework that doesn’t yet include those types, you can instead pick them up from NuGet: • Right-click the project in the Solution Explorer and select "Manage NuGet Packages…" • Select the "Browse" tab and select "nuget.org" as the "Package source" • Search for "System.ValueTuple" and install it. public int Fibonacci(int x) { if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x)); return Fib(x).current; } private (int current, int previous) Fib(int i) { if (i == 0) return (1, 0); var (p, pp) = Fib(i - 1); return (p + pp, p); } Local functions public int Fibonacci(int x) { if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x)); return Fib(x).current; (int current, int previous) Fib(int i) { if (i == 0) return (1, 0); var (p, pp) = Fib(i - 1); return (p + pp, p); } } Local functions private string Tweetify(string msg) { if (msg.Length >= TweetSize) return msg.Substring(0, TweetSize - 3) + "..."; var sb = new StringBuilder(msg); var random = new Random(); while (TryAddHashTag()) { } return sb.ToString(); bool TryAddHashTag() { var r = random.Next(0, Hashtags.Length); var hashtag = " " + Hashtags[r]; if (sb.Length + hashtag.Length > TweetSize) return false; sb.Append(hashtag); return true; } } Local functions public IEnumerable Filter(IEnumerable source, Func filter) { if (source == null) throw new ArgumentNullException(nameof(source)); if (filter == null) throw new ArgumentNullException(nameof(filter)); return Iterator(); IEnumerable Iterator() { foreach (var element in source) { if (filter(element)) { yield return element; } } } } Local functions public async Task Index(int i) { return await GetStuffAsync(); async Task GetStuffAsync() { var someStuff = await GetSomeStuffAsync(i).ConfigureAwait(false); var moreStuff = await GetMoreStuffAsync(i).ConfigureAwait(false); /// ... return result; } } Ref returns and locals public ref int Find(int number, int[] numbers) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == number) { return ref numbers[i]; // return the storage location, not the value } } throw new IndexOutOfRangeException($"{nameof(number)} not found"); } int[] array = { 1, 15, -39, 0, 7, 14, -12 }; ref int place = ref Find(7, array); // aliases 7's place in the array place = 9; // replaces 7 with 9 in the array WriteLine(array[4]); // prints 9 Generalized async return types public async Task GetValueAsync() { return await GetValueMyAsync(); } private abstract MyTask GetValueMyAsync(); public class MyTask { public MyAwaitable GetAwaiter(); } public class MyAwaitable : INotifyCompletion { public bool IsCompleted { get; } public T GetResult(); public void OnCompleted(Action continuation); } public class MyAwaitable : INotifyCompletion, ICriticalNotifyCompletion { public bool IsCompleted { get; } public T GetResult(); public void OnCompleted(Action continuation); public void UnsafeOnCompleted(Action continuation); } Generalized async return types [AsyncMethodBuilder(typeof(MyAsyncMethodBuilder))] public class MyTask { public MyAwaitable GetAwaiter(); } public class MyAsyncMethodBuilder { public static MyAsyncMethodBuilder Create(); public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine; public void SetStateMachine(IAsyncStateMachine stateMachine); public void SetException(Exception exception); public void SetResult(T result); public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine; public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine; public MyTask Task { get; } } Generalized async return types Up until now, async methods in C# must either return void, Task or Task. C# 7.0 allows other types to be defined in such a way that they can be returned from an async method. For instance we now have a ValueTask struct type. It is built to prevent the allocation of a Task object in cases where the result of the async operation is already available at the time of awaiting. For many async scenarios where buffering is involved for example, this can drastically reduce the number of allocations and lead to significant performance gains. There are many other ways that you can imagine custom "task-like" types being useful. It won’t be straightforward to create them correctly, so we don’t expect most people to roll their own, but it is likely that they will start to show up in frameworks and APIs, and callers can then just return and await them the way they do Tasks today. Resources • What's new in C# 7 • https://docs.microsoft.com/dotnet/articles/csharp/whats-new/csharp-7 • New Features in C# 7.0 • https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/ • C# Language Design • https://github.com/dotnet/csharplang/ • .NET Compiler Platform ("Roslyn") • https://github.com/dotnet/roslyn • Visual Studio 2017 • https://www.visualstudio.com/vs/whatsnew/ • LINQPad • http://www.linqpad.net/ https://docs.microsoft.com/dotnet/articles/csharp/whats-new/csharp-7 https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/?Wt.mc_id=DX_MVP8656 https://github.com/dotnet/csharplang/ https://github.com/dotnet/roslyn https://www.visualstudio.com/vs/whatsnew/ http://www.linqpad.net/ PLEASE FILL IN EVALUATION FORMS FRIDAY, MAY 19th SATURDAY, MAY 20th https://survs.com/survey/cprwce7pi8 https://survs.com/survey/l9kksmlzd8 YOUR OPINION IS IMPORTANT! https://survs.com/survey/cprwce7pi8 https://survs.com/survey/l9kksmlzd8 THANK YOU TO OUR SPONSORS PLATINUM GOLD SILVER