Video and slides synchronized, mp3 and slide download available at URL http://bit.ly/2nTR0lc.
Mads Torgersen shares future thinking of a fast-moving major programming language, C#. Torgersen discusses pattern matching, type classes, discriminated unions and much more. Filmed at qconsf.com.
Mads Torgersen leads the C# language design process at Microsoft, where he has been involved in five versions of C#, and also contributed to TypeScript, Visual Basic, Roslyn and LINQ. Before he joined Microsoft, he worked as a university professor in Aarhus, Denmark, doing research into programming language design and contributing to Java generics.
2. InfoQ.com: News & Community Site
• Over 1,000,000 software developers, architects and CTOs read the site world-
wide every month
• 250,000 senior developers subscribe to our weekly newsletter
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• 2 dedicated podcast channels: The InfoQ Podcast, with a focus on
Architecture and The Engineering Culture Podcast, with a focus on building
• 96 deep dives on innovative topics packed as downloadable emags and
minibooks
• Over 40 new content items per week
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
c-sharp-future
3. Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon San Francisco
www.qconsf.com
4. Stack Overflow - most popular technologies
stackoverflow.com/insights/survey/2017#most-popular-technologies
5. Stack Overflow - most loved technologies
stackoverflow.com/insights/survey/2017#most-loved-dreaded-and-wanted
6. Herding nulls – the problem
Every reference type allows null!
Code must be defensive about it
C# shares this with most object oriented languages
Not all languages have this problem
Differentiate between nullable and non-nullable
Use pattern matching or similar to conditionally “unpack” nullables
Components of a solution
Expression of intent (nullable or not?)
Enforcement of intent (regulate assignment and dereference)
Within an existing language!
There are billions of lines of C# code, many of them well-tested against null
7. Herding nulls – expression of intent
public class Person
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
8. Herding nulls – expression of intent
public class Person
{
public string! FirstName { get; set; }
public string? MiddleName { get; set; }
public string! LastName { get; set; }
}
9. Herding nulls – expression of intent
public class Person
{
public string FirstName { get; set; }
public string? MiddleName { get; set; }
public string LastName { get; set; }
}
10. Herding nulls – enforcement
Protect non-null types from nulls
Protect nulls from dereference
Must be optional
Turn it on when you’re ready to know
Can’t affect semantics - warnings, not errors
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)
Can’t be exhaustive
Tradeoff between completeness and convenience
11. Extension everything – new members
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); }
}
12. Extension everything – new members
extension Student extends Person
{
static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>();
public void Enroll(Professor supervisor) { enrollees[this] = supervisor; }
public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null;
public static ICollection<Person> Students => enrollees.Keys;
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;
13. Extension everything – interfaces
extension Student extends Person
{
static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>();
public void Enroll(Professor supervisor) { enrollees[this] = supervisor; }
public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null;
public static ICollection<Person> Students => enrollees.Keys;
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);
}
14. Extension everything – interfaces
extension Student extends Person : IStudent
{
static Dictionary<Person, Professor> enrollees = new Dictionary<Person, Professor>();
public void Enroll(Professor supervisor) { enrollees[this] = supervisor; }
public Professor? Supervisor => enrollees.TryGetValue(this, out var supervisor) ? supervisor : null;
public static ICollection<Person> Students => enrollees.Keys;
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);
}
15. Extension everything – interfaces as type classes
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 });
17. Records
class Person : IEquatable<Person>
{
public string First { get; }
public string Last { get; }
public Person(string First, string Last) => (this.First, this.Last) = (First, Last);
public void Deconstruct(out string First, out string Last)
=> (First, Last) = (this.First, this.Last);
public bool Equals(Person other)
=> other != null && First == other.First && Last == other.Last;
public override bool Equals(object obj) => obj is Person other ? Equals(other) : false;
public override int GetHashCode() => GreatHashFunction(First, Last);
…
}
class Person(string First, string Last);