This document discusses the evolution of C# and .NET Framework over time. It lists various C# versions and their associated .NET Framework versions and Visual Studio versions. It also provides examples of new C# language features such as tuples, nullable reference types, default interface methods, and extension methods.
6. January 2002
•C# 1.0
•Framework 1.0
•VS 2002
April 2003
•C# 1.2
•Framework 1.1
•VS 2003
November 2005
•C# 2.0
•Framework 2.0
•VS 2005
November 2007
•C# 3.0
•Framework 2.0 – 3.5
•VS 2008 & 2010
April 2010
•C# 4.0
•Framework 4.0
•VS 2010
August 2012
•C# 5.0
•Framework 4.5
•VS 2010
July 2015
•C# 6.0
•Framework 4.6
•VS 2015
March 2017
•C# 7.0
•Framework 4.6.2
•VS 2017
August 2017
•C# 7.1
•Framework 4.6.2
•VS 2017 15.3
November 2017
•C# 7.2
•Framework 4.7.1
•VS 2017 15.5
May 2018
•C# 7.3
•Framework 4.7.2
•VS 2017 15.7
7.
8. using static System.Console;
using static System.String;
namespace UsingStaticDirective
{
class Program
{
static void Main(string[] args)
{
int ndx = 0;
foreach (string arg in args)
WriteLine(Format("Argument {0} = {1}", ndx++, arg));
ReadLine();
}
}
}
9. int triesRemaining = 2;
do
{
try
{
DoSomething();
}
catch (ServiceUnavailableException ex) when (ex.ReasonCode == 113)
{
--triesRemaining;
}
} while (triesRemaining > 0);
This feature isn’t just syntactical sugar. It’s been in the CLR from the beginning.
10. class Student
{
public bool Enrolled { get; private set; } = false;
public List<Course> Courses { get; private set; } =
new List<Course>
{
new Course()
{
Name = "Orientation”
}
};
}
11. public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() => String.Format(
"{1}, {0}", FirstName, LastName);
}
13. public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<float> Grades { get; } = new List<float>();
public float GPA => Grades.Average();
public override string ToString() =>
$"{FirstName} {LastName.ToUpper()} : {GPA:F2}";
public string AllGrades() =>
$@"All Grades: {Grades.OrderByDescending(g => g)
.Select(s => s.ToString("F2"))
.Aggregate((partial, element) => $"{partial}, {element}")}";
}
14. public void RegexFormat(string source, int min, int max, string regEx)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (min < 0)
throw new ArgumentOutOfRangeException(nameof(min));
if (max > 100)
throw new ArgumentOutOfRangeException(nameof(max));
if (regEx == null)
throw new ArgumentNullException(nameof(regEx));
if (regEx.Trim().Length == 0)
throw new ArgumentException("May not be empty.", nameof(regEx));
// ...
}
17. int n1 = 0b0000_0000_1111_1111_0000_0000_1111_1111;
int x1 = 0x00_FF_00_FF;
int n2 = 0b0110_1101_0011_1101_1011_1100_0101_1001;
int x2 = 0x6D_3D_BC_59;
// This one won't compile
// int n3 = 0b11101101001111011011110001011001;
Console.WriteLine($"{n1:X} = {x1:X}");
Console.WriteLine($"{n2:X} = {x2:X}");
18. Console.Write("Watermelons are delicious. True or false? ");
string input = Console.ReadLine();
if (Boolean.TryParse(input, out bool answer))
Console.WriteLine(answer ? "Good answer." : "WRONG!");
else
Console.WriteLine("You're mumbling.");
Console.WriteLine($"I can still see your answer ({answer}) out here.");
21. private static (int Max, int Min) Range(IEnumerable<int> numbers) {
int min = int.MaxValue;
int max = int.MinValue;
foreach (var n in numbers) {
min = (n < min) ? n : min;
max = (n > max) ? n : max;
}
return (max, min);
}
List<int> numbers = new List<int>();
Random rng = new Random(DateTime.UtcNow.Millisecond);
for (int ndx = 0; ndx < 10; ndx++)
numbers.Add(rng.Next(0, 1000));
(int max, int min) = Range(numbers);
Console.WriteLine($"min = {min}, max = {max}");
23. public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public void Deconstruct(out string fname,
out string lname, out string city) {
fname = FirstName;
lname = LastName;
city = City;
}
}
Person p = new Person() { FirstName = "Willy",
LastName = "Hughes", City = "Greenville" };
var (first, _, city) = p;
Console.WriteLine($"Welcome {first} of {city}!");
24. // CONST PATTERN
if (o is null) throw new ArgumentNullException(nameof(o));
if (o is 42) Console.WriteLine("it's 42");
// TYPE PATTERN
if (o is int i) Console.WriteLine($"int = {i}");
if (o is Person p) Console.WriteLine($"person = {p.FirstName}");
// VAR PATTERN
if (o is var x) Console.WriteLine($"{x?.GetType()?.Name}");
25. switch (o)
{
case null:
throw new ArgumentNullException(nameof(o));
case 42:
Console.WriteLine("it's 42");
case int i:
Console.WriteLine($"int = {i}");
case Person p:
Console.WriteLine($"person = {p.FirstName}");
case var x:
Console.WriteLine($"{x?.GetType()?.Name}");
}
26. static ref T Find<T>(T[] coll, Func<T, bool> matches) {
for (int ndx = 0; ndx < coll.GetLength(0); ndx++) {
if (matches(coll[ndx]))
return ref coll[ndx];
}
throw new ApplicationException("Not found.");
}
int[] numbers = new int[10];
Random rng = new Random(DateTime.UtcNow.Millisecond);
for (int ndx = 0; ndx < numbers.GetLength(0); ndx++)
numbers[ndx] = rng.Next(0, 10);
Dump(numbers);
ref var x = ref Find(numbers, n => n > 5);
x = -1;
Dump(numbers);
27. public static IEnumerable<string> ReadLineByLine(string fileName)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException(nameof(fileName));
foreach (var line in File.ReadAllLines(fileName))
yield return line;
}
001: string fileName = null;
002: var query = ReadLineByLineLocal(fileName)
.Select(x => $"t{x}")
.Where(l => l.Length > 10);
003: string first = query.First();
public static IEnumerable<string> ReadLineByLineLocal(string fileName)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException(nameof(fileName));
return ReadLineByLineImpl();
IEnumerable<string> ReadLineByLineImpl()
{
foreach (var line in File.ReadAllLines(fileName))
yield return line;
}
}
28. public class Identifier
{
private string label = String.Empty;
public string Label
{
get => label;
set => label = value ?? "empty";
}
}
29. public string Name
{
get => name;
set => name = value ??
throw new ArgumentNullException(nameof(value),
"New name must not be null");
}
34. int count = 5;
string label = "Colors used in the map";
var pair = (count: count, label: label);
int count = 5;
string label = "Colors used in the map";
var pair = (count, label);
35.
36. • New “in” keyword
• Like ref and out
• Guarantees that the value will not be modified
• Returns of “ref readonly”
• Creates a defensive copy of the result
• Enforces read only semantics at compile time
• New “readonly struct” typing
• Immutable value types
• Allows read only references everywhere
• Removes the need for defensive copies
• New “ref struct” typing
• Forces allocation on the stack, never on the heap
• Used as the basis for Span<T>
• New “readonly ref struct” combines the qualities of
“readonly struct” and “ref struct”
39. • public
• private
• protected
• internal
• protected internal
private protected - Access is limited to the containing class or
types derived from the containing class within the current assembly.
40.
41. public class UsingDelegate<T> where T : System.Delegate { }
public class Multicaster<T> where T : System.MulticastDelegate { }
public static Dictionary<int, string> EnumNamedValues<T>()
where T : System.Enum
{
var result = new Dictionary<int, string>();
var values = Enum.GetValues(typeof(T));
foreach (int item in values)
result.Add(item, Enum.GetName(typeof(T), item));
return result;
}
42. var left = (a: 5, b: 10);
var right = (a: 5, b: 10);
(int a, int b)? nullableTuple = right;
(int? a, int? b) nullableMembers = (5, 10);
(long a, long b) longTuple = (5, 10);
Console.WriteLine(left == right); // true
Console.WriteLine(left == nullableTuple); // true
Console.WriteLine(left == nullableMembers); // true
Console.WriteLine(left == longTuple); // true
46. string text1 = null; // Cannot convert null to non-nullable reference
string? text2 = null;
string text3 = text2; // Possible null reference assignment
Console.WriteLine( text2.Length ); // Possible dereference of a null
https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types.md
47. public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
int x = int.Parse(Console.Readline());
if (x.Even)
{
Console.WriteLine(“You’ve typed an even number.”);
}