O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

C#9 - Más C# que nunca

19 visualizações

Publicada em

Slides de mi charla del Talks4Kids 2020 donde hablé un poco sobre las novedades de C#9 (records, pattern matching, init-only properties)

Publicada em: Software
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

C#9 - Más C# que nunca

  1. 1. C#9: Más C# que nunca! Eduard Tomàs @eiximenis https://eiximenis.dev
  2. 2. ¿Quien soy yo? • Cervecero aficionado • Desarrollador en Plain Concepts • Microsoft MVP* desde 2012 hasta la actualidad • https://eiximenis.dev * o eso espero, que hoy hay renovación xD
  3. 3. Un breve recorrido por la historia de C# C# 1 Inspirado en Java: clases, interfaces, events, structs, delegates, properties, attributes C# 2 Genéricos, Tipos parciales, métodos anónimos, iteradores C# 3 Lambdas, Auto-properties, Árboles de expresión, Inferencia de tipos, Métodos de extensión, Tipos anónimos, query expressions, métodos parciales C# 4 Dynamic, parámetros nombrados, varianza en genéricos C# 5 async/await, Caller info attributes
  4. 4. Un breve recorrido por la historia de C# C# 6 Null propagator (?.), auto property inits, expression bodied members, interpolación de cadenas, nameof, static imports, index initializers C# 7 Out variables, tuplas y deconstrucción, pattern matching, funciones locales, property expression bodied, ref locals and returns C# 7.1 async main, pattern matching on generic type parameters, tuple inferred names C# 7.2 in, ref readonly, readonly struct, ref struct, private protected access C# 7.3 Focus en que el código seguro sea igual de rápido que el código inseguro, más restricciones en genéricos (enum, delegate, unmanaged)
  5. 5. Un breve recorrido por la historia de C# C# 8 Métodos readonly, default interface methods, más pattern matching, Índices y rangos, operador ??=, unmanaged constructed types, C# 9 …
  6. 6. Un breve recorrido por la historia de C# C# 8 Métodos readonly, default interface methods, más pattern matching, Índices y rangos, operador ??=, unmanaged constructed types, C# 9 • Init-only properties and init accessors • Records • Top-Level programs • More pattern matching • Target-typed new, ?? and ?: • Covariant returns • …
  7. 7. Esa presentación es de algo que está en preview Lo que está aquí puede cambiar… o no xD
  8. 8. Init properties • Propiedades que solo se pueden inicializar al crear el objeto public class Beer { public string Name {get; init;} } var mahou = new Beer() { Name="Mahou"} mahou.Name="Mahou 5 estrellas"; // ERROR!!! 👍 Evita constructores con muchas sobrecargas/parámetros
  9. 9. Records • La GRAN novedad de C#9 • Definen objetos con semántica de valor (como las structs) • Pensados para objetos inmutables (a diferencia de las structs)
  10. 10. Records – Semántica de valor Semántica de valor (Equals y GetHashCode autogenerado) A día de hoy operadores = y == se comportan con semántica de referencia public record Beer { public string Name {get; init;} public double Abv {get; init;} } var mahou = new Beer() {Name = "Mahou", Abv=4.3}; var mahou2 = new Beer() {Name = "Mahou", Abv=4.3}; mahou.Equals(mahou2); // TRUE
  11. 11. Records - With • Clona un record y modifica propiedades sobre el record clonado public record Beer { public string Name {get; init;} public double Abv {get; init;} } var mahou = new Beer() {Name = "Mahou", Abv = 4.3}; var mahou5 = mahou with { Name = "Mahou 5 estrellas"};
  12. 12. Records – Constructor de copia • Todos los records tienen un constructor de copia generado por el compilador que es usado por with public record Beer { public string Name {get; init;} public double Abv {get; init;} } public record Beer { public string Name {get; init;} public double Abv {get; init;} public Beer(){} protected Beer (Beer other) {Name = other.Name; Abv=other.Abv;} } • Lo podemos redefinir
  13. 13. Records – Parámetros posicionales • Se pueden declarar parámetros posicionales que se pasan en el constructor • La deconstrucción se soporta automáticamente public record Beer (string Name, double Abv); var mahou = new Beer("Mahou", 5.4); var (_,abv) = mahou;
  14. 14. Records – Parámetros posicionales • Los parámetros posicionales son propiedades init public record Beer (string Name="", double Abv=default); var mahou = new Beer("Mahou", 5.4); var estrella = new Beer("Estrella") {Abv=3.2}; var vollDamm = new Beer(Abv: 7.4) { Name = "Voll Damm"};
  15. 15. Records – Herencia e igualdad • La herencia añade complejidad a la igualdad • Si x.Equals(y) entonces debe cumplirse que y.Equals(x) public record Beer { public string Name {get; init;} public double Abv {get; init;} } public record PricedBeer : Beer { public decimal Price {get; init; } } var mahou = new Beer {Name="Mahou", Abv=4.3}; var mahouOferta = new PricedBeer {Name="Mahou", Abv=4.3, Price=1M}; mahou.Equals(mahouOferta); // ?????????
  16. 16. Records – Herencia e igualdad • Desde el punto de vista de mahou, ambos objetos son iguales (tienen mismo nombre y abv) • Desde el punto de vista de mahouOferta ambos objetos son distintos • Cada record tiene una propiedad protected (Type EqualityContract) que es usada por el método Equals generado • Ojo si sobreescribimos Equals!
  17. 17. Pattern Matching public record Beer { public string Name {get; init;} public double Abv {get; init;} } int AlcoholicGrade (in Beer beer) { var alcoholicGrade = 0; if (beer.Abv == 0.0) {alcoholicGrade=0;} else if (beer.Abv > 0 && beer.Abv < 1) {alcoholicGrade=1;} else if (beer.Abv >1 && beer.Abv < 5) {alcoholicGrade=2;} else alcoholicGrade = 3; return alcoholicGrade; }
  18. 18. Pattern Matching public record Beer { public string Name {get; init;} public double Abv {get; init;} } int AlcoholicGrade (in Beer beer) => beer.Abv switch { 0.0 => 0, >0 and <1 => 1, >1 and <5 => 2, _ => 3 }; int AlcoholicGrade (in Beer beer) => beer.Abv switch { 0.0 => 0, <1 => 1, <5 => 2, _ => 3 };
  19. 19. Pattern Matching – ¿Quien quiere ifs? • Supongamos que el nivel de graduación es distinto para IPAs que para otras cervezas… public record Beer { public string Name {get; init;} public double Abv {get; init;} } public record IPA : Beer {} int AlcoholicGrade (in Beer beer) => beer switch { IPA ipa => ipa.Abv switch { 0.0 => 0, >0 and <5 => 1, >5 and <10 => 2, _ => 3 }, Beer => beer.Abv switch { 0.0 => 0, >0 and <1 => 1, >1 and <5 => 2, _ => 3 } }; var impaled = new IPA() {Name="IMPALED", Abv=9.5}; var megaMahou = new Beer() {Name="Mahou", Abv=9.5}; var grade = AlcoholicGrade(impaled); // 2 var grade2 = AlcoholicGrade(megaMahou); // 3
  20. 20. Retornos covariantes • Cuando se diseña una API puede dares el caso de querer sobreescribir una función heredada pero cambiar el valor de retorno por uno más especifico class WebResponse { } class WebRequest { protected virtual WebResponse GetResponse() { … } } class FtpWebResponse : WebResponse { } class FtpWebRequest : WebRequest { protected override WebResponse GetResponse() { … } } Aquí nos intersaría poder devolver un FtpWebResponse pero estamos obligados a devolver un WebResponse Los clientes de FtpWebRequest siempre deben ir haciendo casts Retornos covariantes permitirá eso
  21. 21. Otras pequeñas mejoras • is not (por fin!! No más !(x is Foo)) • Target type new ( y de ?? y de ?: ) IPA impaled = new() {Name = "IMPALED", Abv=9.5}; () es necesario • Top-Level programs (Main no necesario, ideal para Hello Worlds) • ¡Y más… mucho más! https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md
  22. 22. ¡Gracias! Eduard Tomàs @eiximenis

×