Что нам готовит грядущий c#7?
TRANSCRIPT
Что нам готовит грядущий C#7?
Андрей Акиньшин, JetBrains
Community Dev Camp 2015
1/27
C#7
2/27
Tuples (Background)
public void Tally(IEnumerable<int> values, out int sum, out int count)
int s, c;Tally(myValues, out s, out c);Console.WriteLine($"Sum: {s}, count: {c}");
public Tuple<int, int> Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Item1}, count: {t.Item2}")
public struct TallyResult { public int Sum; public int Count; }public TallyResult Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Sum}, count: {t.Count}");
3/27
Tuples (Background)
public void Tally(IEnumerable<int> values, out int sum, out int count)
int s, c;Tally(myValues, out s, out c);Console.WriteLine($"Sum: {s}, count: {c}");
public Tuple<int, int> Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Item1}, count: {t.Item2}")
public struct TallyResult { public int Sum; public int Count; }public TallyResult Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Sum}, count: {t.Count}");
3/27
Tuples (Background)
public void Tally(IEnumerable<int> values, out int sum, out int count)
int s, c;Tally(myValues, out s, out c);Console.WriteLine($"Sum: {s}, count: {c}");
public Tuple<int, int> Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Item1}, count: {t.Item2}")
public struct TallyResult { public int Sum; public int Count; }public TallyResult Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Sum}, count: {t.Count}");
3/27
Tuples (Background)
public void Tally(IEnumerable<int> values, out int sum, out int count)
int s, c;Tally(myValues, out s, out c);Console.WriteLine($"Sum: {s}, count: {c}");
public Tuple<int, int> Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Item1}, count: {t.Item2}")
public struct TallyResult { public int Sum; public int Count; }public TallyResult Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.Sum}, count: {t.Count}");
3/27
Tuples types
public (int sum, int count) Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.sum}, count: {t.count}");
public async Task<(int sum, int count)>TallyAsync(IEnumerable<int> values)
var t = await TallyAsync(myValues);Console.WriteLine($"Sum: {t.sum}, count: {t.count}");
4/27
Tuples types
public (int sum, int count) Tally(IEnumerable<int> values)
var t = Tally(myValues);Console.WriteLine($"Sum: {t.sum}, count: {t.count}");
public async Task<(int sum, int count)>TallyAsync(IEnumerable<int> values)
var t = await TallyAsync(myValues);Console.WriteLine($"Sum: {t.sum}, count: {t.count}");
4/27
Tuple literals and deconstruction
var t = new (int sum, int count) { sum = 0, count = 0 };
public (int sum, int count) Tally(IEnumerable<int> values){
var s = 0; var c = 0;foreach (var value in values) { s += value; c++; }
return (s, c); // target typed to (int sum, int count)}
public (int sum, int count) Tally(IEnumerable<int> values){
// infer tuple type from names and valuesvar res = (sum: 0, count: 0);foreach (var value in values) { res.sum += value; res.count++; }
return res;}
(var sum, var count) = Tally(myValues); // deconstruct resultConsole.WriteLine($"Sum: {sum}, count: {count}");
5/27
Tuple literals and deconstruction
var t = new (int sum, int count) { sum = 0, count = 0 };
public (int sum, int count) Tally(IEnumerable<int> values){
var s = 0; var c = 0;foreach (var value in values) { s += value; c++; }
return (s, c); // target typed to (int sum, int count)}
public (int sum, int count) Tally(IEnumerable<int> values){
// infer tuple type from names and valuesvar res = (sum: 0, count: 0);foreach (var value in values) { res.sum += value; res.count++; }
return res;}
(var sum, var count) = Tally(myValues); // deconstruct resultConsole.WriteLine($"Sum: {sum}, count: {count}");
5/27
Tuple literals and deconstruction
var t = new (int sum, int count) { sum = 0, count = 0 };
public (int sum, int count) Tally(IEnumerable<int> values){
var s = 0; var c = 0;foreach (var value in values) { s += value; c++; }
return (s, c); // target typed to (int sum, int count)}
public (int sum, int count) Tally(IEnumerable<int> values){
// infer tuple type from names and valuesvar res = (sum: 0, count: 0);foreach (var value in values) { res.sum += value; res.count++; }
return res;}
(var sum, var count) = Tally(myValues); // deconstruct resultConsole.WriteLine($"Sum: {sum}, count: {count}");
5/27
Tuple literals and deconstruction
var t = new (int sum, int count) { sum = 0, count = 0 };
public (int sum, int count) Tally(IEnumerable<int> values){
var s = 0; var c = 0;foreach (var value in values) { s += value; c++; }
return (s, c); // target typed to (int sum, int count)}
public (int sum, int count) Tally(IEnumerable<int> values){
// infer tuple type from names and valuesvar res = (sum: 0, count: 0);foreach (var value in values) { res.sum += value; res.count++; }
return res;}
(var sum, var count) = Tally(myValues); // deconstruct resultConsole.WriteLine($"Sum: {sum}, count: {count}");
5/27
Tuples: проблемы
• Struct or class• Mutability• Tuples as fields• Conversions• . . .
Cм. также: roslyn#347
6/27
Pattern matching (Background)// class Person(string Name);class Person{
public Person(string name) { this.Name = name; }public string Name { get; }
}
// class Student(string Name, double Gpa) : Person(Name);class Student : Person{
public Student(string name, double gpa) : base(name){ this.Gpa = gpa; }
public double Gpa { get; }}
// class Teacher(string Name, string Subject) : Person(Name);class Teacher : Person{
public Teacher(string name, string subject) : base(name){ this.Subject = subject; }
public string Subject { get; }}
7/27
Pattern matching (Background)static string PrintedForm(Person p){
Student s;Teacher t;if ((s = p as Student) != null && s.Gpa > 3.5){
return $"Honor Student {s.Name} ({s.Gpa})";}else if (s != null){
return $"Student {s.Name} ({s.Gpa})";}else if ((t = p as Teacher) != null){
return $"Teacher {t.Name} of {t.Subject}";}else{
return $"Person {p.Name}";}
}
8/27
Pattern matching (Background)
static void Main(string[] args){
Person[] oa = {new Student("Einstein", 4.0),new Student("Elvis", 3.0),new Student("Poindexter", 3.2),new Teacher("Feynmann", "Physics"),new Person("Anders"),
};foreach (var o in oa){
Console.WriteLine(PrintedForm(o));}Console.ReadKey();
}
9/27
Pattern matching: is
static string PrintedForm(Person p){
if (p is Student s && s.Gpa > 3.5){
return $"Honor Student {s.Name} ({s.Gpa})";}else if (p is Student s){
return $"Student {s.Name} ({s.Gpa})";}else if (p is Teacher t){
return $"Teacher {t.Name} of {t.Subject}";}else{
return $"Person {p.Name}";}
}
10/27
Pattern matching: switch
static string PrintedForm(Person p){
switch (p){
case Student s when s.Gpa > 3.5 :return $"Honor Student {s.Name} ({s.Gpa})";
case Student s :return $"Student {s.Name} ({s.Gpa})";
case Teacher t :return $"Teacher {t.Name} of {t.Subject}";
default :return $"Person {p.Name}";
}}
11/27
Pattern matching: match
static string PrintedForm(Person p){
return p match (case Student s when s.Gpa > 3.5 :
$"Honor Student {s.Name} ({s.Gpa})"case Student s :
$"Student {s.Name} ({s.Gpa})"case Teacher t :
$"Teacher {t.Name} of {t.Subject}"case * :
$"Person {p.Name}");
}
12/27
Pattern matching: Exceptions
return p match (case Student s when s.Gpa > 3.5 :
$"Honor Student {s.Name} ({s.Gpa})"case Student s :
$"Student {s.Name} ({s.Gpa})"case Teacher t :
$"Teacher {t.Name} of {t.Subject}"case null :
throw new ArgumentNullException(nameof(p))case * :
$"Person {p.Name}");
13/27
Pattern matching: members
return p match (case Student s when s.Gpa > 3.5 :
$"Honor Student {s.Name} ({s.Gpa})"case Student { Name is "Poindexter" } :
"A Nerd"case Student s :
$"Student {s.Name} ({s.Gpa})"case Teacher t :
$"Teacher {t.Name} of {t.Subject}"case null :
throw new ArgumentNullException(nameof(p))case * :
$"Person {p.Name}");
14/27
Pattern matching: =>
static string PrintedForm(Person p) => p match (case Student s when s.Gpa > 3.5 :
$"Honor Student {s.Name} ({s.Gpa})"case Student { Name is "Poindexter" } :
"A Nerd"case Student s :
$"Student {s.Name} ({s.Gpa})"case Teacher t :
$"Teacher {t.Name} of {t.Subject}"case null :
throw new ArgumentNullException(nameof(p))case * :
$"Person {p.Name}");
15/27
Readonly locals
readonly int foo = /* ... */ ;readonly var foo = /* ... */ ;val foo = /* ... */ ;public void Bar(readonly int foo = 0)public void Bar(readonly ref Matrix3D matrix)
16/27
Immutable Typespublic immutable struct Tuple<T1, T2>{
public Tuple(T1 item1, T2 item2){ Item1 = item1; Item2 = item2; }
public T1 Item1; // Implicitly readonlypublic T2 Item2; // Implicitly readonly
}
public immutable struct ImmutableTuple<T1, T2>(T1 item1, T2 item2)
where T1 : immutablewhere T2 : immutable
{public ImmutableTuple(T1 item1, T2 item2)
{ Item1 = item1; Item2 = item2; }public T1 Item1;public T2 Item2;
}
17/27
Immutable Typespublic immutable struct Tuple<T1, T2>{
public Tuple(T1 item1, T2 item2){ Item1 = item1; Item2 = item2; }
public T1 Item1; // Implicitly readonlypublic T2 Item2; // Implicitly readonly
}
public immutable struct ImmutableTuple<T1, T2>(T1 item1, T2 item2)
where T1 : immutablewhere T2 : immutable
{public ImmutableTuple(T1 item1, T2 item2)
{ Item1 = item1; Item2 = item2; }public T1 Item1;public T2 Item2;
}
17/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен3 Процесс компиляции не меняется4 Runtime ничего не знает про not-nullable5 Обратная совместимость
18/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен3 Процесс компиляции не меняется4 Runtime ничего не знает про not-nullable5 Обратная совместимость
18/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен
3 Процесс компиляции не меняется4 Runtime ничего не знает про not-nullable5 Обратная совместимость
18/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен3 Процесс компиляции не меняется
4 Runtime ничего не знает про not-nullable5 Обратная совместимость
18/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен3 Процесс компиляции не меняется4 Runtime ничего не знает про not-nullable
5 Обратная совместимость
18/27
Nullability?!
1 Добавляем в язык только ? и ! приобъявления и кастах
2 NullReferenceException невозможен3 Процесс компиляции не меняется4 Runtime ничего не знает про not-nullable5 Обратная совместимость
18/27
Local functions
static void Main(string[] args){
int Fib(int n) => (n < 2)? 1: Fib(n - 1) + Fib(n - 2);
Console.WriteLine(Fib(7));}
19/27
Extensions properties
public static class MyClassExtensions{
public static int Data[this MyClass obj]{
get { return 0; }set { return; }
}}var data = myObj.Data;myObj.Data = 1;
20/27
Binary literals and Digits separators
int bin = 0b1001_1010_0001_0100;int hex = 0x1b_a0_44_fe;int dec = 33_554_432;int weird = 1_2__3___4____5_____6______7_______8________9;double real = 1_000.111_1e-1_000;
21/27
params IEnumerable
WriteLine(params object[] args)WriteLine(params IEnumerable<object> args)
22/27
Method contracts
public int Insert(T item, int index){
Contract.Requires(index >= 0 && index <= Count);Contract.Ensures(Contract.Result<int>() >= 0 &&
Contract.Result<int>() < Count);return InsertCore(item, index);
}
public int Insert(T item, int index)requires index >= 0 && index <= Countensures return >= 0 && return < Count
{return InsertCore(item, index);
}
23/27
Method contracts
public int Insert(T item, int index){
Contract.Requires(index >= 0 && index <= Count);Contract.Ensures(Contract.Result<int>() >= 0 &&
Contract.Result<int>() < Count);return InsertCore(item, index);
}
public int Insert(T item, int index)requires index >= 0 && index <= Countensures return >= 0 && return < Count
{return InsertCore(item, index);
}
23/27
corefxlab: System.Slices
public partial struct Span<T> : IEnumerable<T>, IEquatable<Span<T>>{
readonly object _object;readonly UIntPtr _offset;public readonly int Length;// ...Span(T[] array, int start, int length)unsafe Span(void* ptr, int length)bool TryCopyTo(Span<T> dest)Span<T> Slice(int start, int length)
}
// Extensionsstatic Span<T> Slice<T>(this T[] array, int start, int length)static Span<char> Slice(this string str, int start, int length)static Span<U> Cast<[Primitive]T, [Primitive]U>(this Span<T> slice)static bool SequenceEqual<T>(this Span<T> first, Span<T> second)// ...
24/27
Array slicing syntax
int[] primes = new int[] { 2, 3, 5, 7, 9, 11, 13 };int item = primes[1]; // Regular array access (value 3)int[:] a = primes[0:3]; // A slice {2, 3, 5}int[:] b = primes[1:2]; // A slice {3}int[:] c = primes[:5]; // A slice {2, 3, 5, 7, 9}int[:] d = primes[2:]; // A slice {5, 7, 9, 11, 13}int[:] e = primes[:]; // A slice {2, 3, 5, 7, 9, 11, 13}int[:] f = a[1:2]; // A slice {3}int[:] g = primes[:]; // A slice {2, 3, 5, 7, 9, 11, 13}int[:] h = primes; // A slice {2, 3, 5, 7, 9, 11, 13}int[:] i = h[:]; // A slice {2, 3, 5, 7, 9, 11, 13}
25/27
github
26/27
Вопросы?
Андрей Акиньшин, JetBrainshttp://aakinshin.net
https://github.com/AndreyAkinshinhttps://twitter.com/andrey_akinshin
27/27