- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
微软 Mads Torgersen《以Null的处理、回调地狱的应对为例,看C#背后的问题解决思路》
展开查看详情
1 .Herding Nulls and other C# stories from the future Mads Torgersen, C# lead designer Microsoft
2 . Chapter One Herding nulls
3 .Every reference type allows null! Code must be defensive about it C# shares this with most object oriented languages
4 .Not all languages have this problem! Differentiate between nullable and non-nullable Use pattern matching to conditionally “unpack” nullables
5 .1. Expression of intent 2. Enforcement of intent Within an existing language!
6 .public class Person { public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } }
7 .public class Person { public string! FirstName { get; set; } } public string? MiddleName { get; set; } public string! LastName { get; set; } L
8 .public class Person { public string! FirstName { get; set; } } public string MiddleName { get; set; } public string! LastName { get; set; } L
9 .public class Person { public string FirstName { get; set; } } public string? MiddleName { get; set; } public string LastName { get; set; } J
10 .1. Protect non-null types from nulls 2. Protect nulls from dereference
11 .Must be optional Turn it on when you’re ready to know Can’t affect semantics - warnings, not errors
12 .Must do a good job with existing code Can’t force you to rewrite good code Recognize existing ways of ensuring null safety (checks and assignments)
13 .Can’t be exhaustive Tradeoff between completeness and convenience
14 . Color illustration Nullable reference types
15 . Chapter Two Async streams
16 . Chapter Three Extension everything
17 .extension Student extends Person { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } }
18 .extension Student extends Person { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } Person mads = new Person("Mads Torgersen", tonyHoare);
19 .extension Student extends Person { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } Person mads = new Person("Mads Torgersen", tonyHoare); WriteLine(mads.Supervisor);
20 .extension Student extends Person { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } Person mads = new Person("Mads Torgersen", tonyHoare); WriteLine(mads.Supervisor); var tonysStudents = from s in Person.Students where s.Supervisor == tonyHoare select s.Name;
21 .extension Student extends Person { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } class Professor { … } interface IStudent { string Name { get; } Professor? Supervisor { get; } void Enroll(Professor supervisor); }
22 .extension Student extends Person : IStudent { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } class Professor { … } interface IStudent { string Name { get; } Professor? Supervisor { get; } void Enroll(Professor supervisor); }
23 .extension Student extends Person : IStudent { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } class Professor { … } interface IStudent { string Name { get; } Professor? Supervisor { get; } void Enroll(Professor supervisor); }
24 .extension Student extends Person : IStudent { // static field static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>(); // instance method public void Enroll(Professor supervisor) { enrollees[this] = supervisor; } // instance property public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null; // static property public static ICollection<Person> Students => enrollees.Keys; // instance constructor public Person(string name, Professor supervisor) : this(name) { this.Enroll(supervisor); } } class Professor { … } interface IStudent { string Name { get; } Professor? Supervisor { get; } void Enroll(Professor supervisor); }
25 .interface IGroup<T> { static T Zero { get; } static T operator +(T t1, T t2); } extension IntGroup extends int : IGroup<int> { public static int T Zero => 0; } public static T AddAll<T>(T[] ts) where T : IGroup<T> { T result = T.Zero; foreach (T t in ts) { result += t; } return result; } int sixtyThree = AddAll(new [] { 1, 2, 4, 8, 16, 32 });
26 .docs.microsoft.com/dotnet/csharp blogs.msdn.microsoft.com/dotnet github.com/dotnet/csharplang