Алексей Соммер
New C# features
C# 1.0 Visual Studio 2002
Retrospective
C# 2.0 Visual Studio 2005 - Generics, Anonymous methods, iterators/yield, static classes
C# 3.0 Visual Studio 2008 - LINQ, Lambda Expressions, Implicit typing, Extension methods
C# 6.0 Visual Studio 2015 - Null-conditional operators, String Interpolation
C# 5.0 Visual Studio 2012 - async/await, Caller Information, some breaking changes
C# 4.0 Visual Studio 2010 - dynamic, Optional parameters and named arguments
C# 7.0 Visual Studio 2017 - Tuples, Pattern matching, Local functions
C# 1.1 Visual Studio 2003 - #line, pragma, xml doc comments
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
OnPropertyChanged(); OnPropertyChanged("Price");
From F# to C#
Tuples
LINQ
Immutability
Pattern matching
Exception filters
Auto-property initializers
Expression-bodied function members
try
{
SomeMethod(param);
}
catch (Exception e) when (param != null)
{
}
Exception filters
public string AppUrl { get; set; } = "http://lalala.com";
public string AppUrl { get; set; } = InitializeProperty();
public static string InitializeProperty()
{
return "http://lalala.com ";
}
Auto-property initializers
public int Sum(int x, int y)
{
return x+y;
}
public string ServerIP { get { return "65.23.135.201"; } }
public int Sum(int x, int y) => x+y;
public string ServerIP => "65.23.135.201";
Expression-bodied function members
C# 7 Work List of Features
bit.ly/1E1nrJZ
Language Feature Status
bit.ly/1TKZAHc
Tuples
There no need anymore to create new class if you want to
send or get multiple parameters!
var unnamed = (35, "What is your age?");
unnamed.Item1 == named.Answer
var named = (Answer: 35, Question: "What’s your age again?");
(int, string) GetXY()
{
int x = 1;
string y = "One";
return (x, y);
}
Simplest example
var xy = GetXY();
Deconstruction
(int, List<string>) GetListWithId()
{
int x = 1;
List<string> y = new List<string>();
return (x, y);
}
(int x, List<string> y) = GetListWithId();
var (x, y) = GetXY();
public class Coordinates
{
public int X { get; }
public int Y { get; }
public Coordinates(int x, int y)
{
X = x;
Y = y;
}
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}
Coordinates xy =
new Coordinates(5, 7);
(int x, int y) = xy;
User defined types
Pattern Matching
if (someObject is Customer)
{
var c = (Customer)someObject;
c.Balance = c.Balance + 1000;
}
if (someObject is Customer c) c.Balance = c.Balance + 1000;
switch (userRole)
{
case Manager m:
return m.Salary;
case Partner p:
return p.Income;
}
Case
switch (userRole)
{
case Manager m with Salary<1500:
return m.Salary*1.2;
case Manager m:
return m.Salary;
case Partner p:
return p.Income;
}
Case …. with
C# 7.1 features
Async Main
default literal
Infer tuple names
Pattern-matching with generics
Reference assemblies
static void Main(string[] args)
{
DoWork().GetAwaiter().GetResult();
}
static void Main(string[] args)
{
DoWork().Wait();
}
static async Task DoWork() { }
any exception
AggregateException
Boilerplate code
async Main
default
int i = default;
Instead of
int i = default(int);
Infer Tuple Names
explicit names
var tuple = (a: x.a, y: x.y);
inferred names
var tuple = (x.a, y);
Infer tuple names
int x=1;
Action y = () => SomeMethod();
var tuple = (a: x, y);
tuple.y();
Aaa! It’s breaking back compatibility!
// previously
public static class ExtClass
{
public static void y(this (int, Action) z)
{
}
}
// now
void SomeMethod() { }
Pattern-matching with generics
class Manager : Person { }
class Employee : Person { }
……………
Employee m = new Employee();
IncreaseSalary<Employee>(m);
……………
public void IncreaseSalary<T>(T person) where T : Person
{
if (person is Manager m) person.Salary++;
}
Readonly ref
static Employee CreateCopy(ref Position p)
{
// don’t change p value!
return new Position() { Lat = p.Lat, Long = p.Long };
}
static Employee CreateCopy(ref readonly Position p)
{
p.Lat = 54.32654;
SomeMethod(ref p.Lat);
return new Position() { Lat = p.Lat , Long = p.Long };
}
Non-trailing named arguments
int SomeMethod(int x, int y)
{
return (x - y) * (x + y);
}
SomeMethod(11, 27)
SomeMethod(y:17, x:21)
SomeMethod(11, y:27)
SomeMethod(x:12, 11)
Why?
int SomeMethod(int y, int x) { return 1; }
int SomeMethod<T>(int x, T y) { return 2; }
SomeMethod(x: 17, y: 21); // calls first SomeMethod
SomeMethod(11, y: 27); // calls second SomeMethod
Drawbacks
blittable
blittable struct BlittableOrNot
{
public byte a;
public bool b;
public int c;
}
blittable struct BlittableOrNot
{
public byte a;
public double b;
public int c;
}
Default Interface Methods
1. Currently if you want to change interface then you should change
all implementations
2. What if class will try to implement two interfaces having a default
method with the same signature?
3. Interfaces are still different from abstract classes
> Спасибо за внимание!
> Алексей Соммер
> asommer@yandex.ru
> skype: alexejsommer

New C# features

  • 1.
  • 2.
    C# 1.0 VisualStudio 2002 Retrospective C# 2.0 Visual Studio 2005 - Generics, Anonymous methods, iterators/yield, static classes C# 3.0 Visual Studio 2008 - LINQ, Lambda Expressions, Implicit typing, Extension methods C# 6.0 Visual Studio 2015 - Null-conditional operators, String Interpolation C# 5.0 Visual Studio 2012 - async/await, Caller Information, some breaking changes C# 4.0 Visual Studio 2010 - dynamic, Optional parameters and named arguments C# 7.0 Visual Studio 2017 - Tuples, Pattern matching, Local functions C# 1.1 Visual Studio 2003 - #line, pragma, xml doc comments
  • 3.
    public event PropertyChangedEventHandlerPropertyChanged; public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } OnPropertyChanged(); OnPropertyChanged("Price");
  • 4.
    From F# toC# Tuples LINQ Immutability Pattern matching Exception filters Auto-property initializers Expression-bodied function members
  • 5.
    try { SomeMethod(param); } catch (Exception e)when (param != null) { } Exception filters
  • 6.
    public string AppUrl{ get; set; } = "http://lalala.com"; public string AppUrl { get; set; } = InitializeProperty(); public static string InitializeProperty() { return "http://lalala.com "; } Auto-property initializers
  • 7.
    public int Sum(intx, int y) { return x+y; } public string ServerIP { get { return "65.23.135.201"; } } public int Sum(int x, int y) => x+y; public string ServerIP => "65.23.135.201"; Expression-bodied function members
  • 8.
    C# 7 WorkList of Features bit.ly/1E1nrJZ Language Feature Status bit.ly/1TKZAHc
  • 9.
    Tuples There no needanymore to create new class if you want to send or get multiple parameters! var unnamed = (35, "What is your age?"); unnamed.Item1 == named.Answer var named = (Answer: 35, Question: "What’s your age again?");
  • 10.
    (int, string) GetXY() { intx = 1; string y = "One"; return (x, y); } Simplest example var xy = GetXY();
  • 11.
    Deconstruction (int, List<string>) GetListWithId() { intx = 1; List<string> y = new List<string>(); return (x, y); } (int x, List<string> y) = GetListWithId(); var (x, y) = GetXY();
  • 12.
    public class Coordinates { publicint X { get; } public int Y { get; } public Coordinates(int x, int y) { X = x; Y = y; } public void Deconstruct(out int x, out int y) { x = X; y = Y; } } Coordinates xy = new Coordinates(5, 7); (int x, int y) = xy; User defined types
  • 13.
    Pattern Matching if (someObjectis Customer) { var c = (Customer)someObject; c.Balance = c.Balance + 1000; } if (someObject is Customer c) c.Balance = c.Balance + 1000;
  • 14.
    switch (userRole) { case Managerm: return m.Salary; case Partner p: return p.Income; } Case
  • 15.
    switch (userRole) { case Managerm with Salary<1500: return m.Salary*1.2; case Manager m: return m.Salary; case Partner p: return p.Income; } Case …. with
  • 16.
    C# 7.1 features AsyncMain default literal Infer tuple names Pattern-matching with generics Reference assemblies
  • 17.
    static void Main(string[]args) { DoWork().GetAwaiter().GetResult(); } static void Main(string[] args) { DoWork().Wait(); } static async Task DoWork() { } any exception AggregateException Boilerplate code async Main
  • 18.
    default int i =default; Instead of int i = default(int);
  • 19.
    Infer Tuple Names explicitnames var tuple = (a: x.a, y: x.y); inferred names var tuple = (x.a, y);
  • 20.
    Infer tuple names intx=1; Action y = () => SomeMethod(); var tuple = (a: x, y); tuple.y(); Aaa! It’s breaking back compatibility! // previously public static class ExtClass { public static void y(this (int, Action) z) { } } // now void SomeMethod() { }
  • 21.
    Pattern-matching with generics classManager : Person { } class Employee : Person { } …………… Employee m = new Employee(); IncreaseSalary<Employee>(m); …………… public void IncreaseSalary<T>(T person) where T : Person { if (person is Manager m) person.Salary++; }
  • 22.
    Readonly ref static EmployeeCreateCopy(ref Position p) { // don’t change p value! return new Position() { Lat = p.Lat, Long = p.Long }; } static Employee CreateCopy(ref readonly Position p) { p.Lat = 54.32654; SomeMethod(ref p.Lat); return new Position() { Lat = p.Lat , Long = p.Long }; }
  • 23.
    Non-trailing named arguments intSomeMethod(int x, int y) { return (x - y) * (x + y); } SomeMethod(11, 27) SomeMethod(y:17, x:21) SomeMethod(11, y:27) SomeMethod(x:12, 11) Why?
  • 24.
    int SomeMethod(int y,int x) { return 1; } int SomeMethod<T>(int x, T y) { return 2; } SomeMethod(x: 17, y: 21); // calls first SomeMethod SomeMethod(11, y: 27); // calls second SomeMethod Drawbacks
  • 25.
    blittable blittable struct BlittableOrNot { publicbyte a; public bool b; public int c; } blittable struct BlittableOrNot { public byte a; public double b; public int c; }
  • 26.
    Default Interface Methods 1.Currently if you want to change interface then you should change all implementations 2. What if class will try to implement two interfaces having a default method with the same signature? 3. Interfaces are still different from abstract classes
  • 27.
    > Спасибо завнимание! > Алексей Соммер > asommer@yandex.ru > skype: alexejsommer

Editor's Notes

  • #3 Does someone use Caller information or even someone know what is it?
  • #4 Можно получить имя вызывающего метод объекта
  • #5 “Invasion” was started in C# 6
  • #6 C# 6
  • #7 C# 6
  • #8 Old style on top and new style on the bottom Works for methods and read-only properties C# 6
  • #9 Whole information is publicly used. You can stalking Mads Torgersen. For example in his last post he is discussing “nullable reference types“
  • #10 NuGet package System.ValueTuple should be installed on .NET 4.6.2 and lower. But VS will inform you about That is probably why we are still not using this feature Спасибо залу за подсказки! Tuples действительно похожи на Anonymous Types. Но anonymous types все-таки не рекомендуется использовать для возврата значения из метода: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types
  • #13 Deconstruction of user defined types If you can’t change the class then you could use Extensions (from C# 3.0) and add static void Deconstruct method
  • #14 Check is object of some type and cast to that type
  • #17 First version since 2002 with minor version in number
  • #22 Let’s say its just something like a bug fix An expression of type T cannot be handled by a pattern of type Manager
  • #23 Pass struct variables into method calls for readonly purposes
  • #24 Named method argument is on his right place, but method couldn’t be called. Why? C# 7.2
  • #25 As you can see from this code drawbacks have exist before this new feature So, probably drawbacks are not drawbacks. More like fix
  • #26 In proposal state for 7.2 Feature could be useful if you are using P/Invoke (you can only return blittable types) Common representation in both managed and unmanaged memory and do not require special handling by the interop marshaler And all objects in memory are placed in consistent order Those type help to share information between managed and unmanaged code Usable in COM Interop or P/Invoke, two techniques for interoperability in .NET applications System.Byte, System.SByte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.IntPtr, System.UIntPtr, System.Single, System.Double
  • #27 As previously all features where from F# - now this feature has come from Java So it would be possible to change legacy code. May be it is more needed for C# development team to add new features  (like it did java developers team) In JAVA it has helped to enhance the Collections API to support lambda expressions 2. As it done in Java default method should be overridden and could be called interface method explicitly