-
-
Save tuannguyenssu/2343b9e4fd42c86ccf29269442a838fe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//-------------------------------------------------------------------------------------- | |
// C# 8.0 Features - Các tính năng nổi bật trên phiên bản C# 8.0 | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// 1. Indices and Range | |
//-------------------------------------------------------------------------------------- | |
var people = new string[] { "Jane", "Jean", "Grey", "Marcus", "Theophilus", "Keje" }; | |
//-------------------------------------------------------------------------------------- | |
// Lấy ra các phần tử trong mảng | |
var all = people[..]; // Lấy ra tất cả các phần tử và đưa vào một biến mới | |
var firstFour = people[..4]; // Lấy ra 4 phần tử đầu tiên "Jane", "Jean", "Grey", and "Marcus" | |
var lastTwo = people[4..]; // Lấy ra 2 phần tử cuối cùng "Theophilus" and "Keje" | |
//-------------------------------------------------------------------------------------- | |
// Lấy ra các phần tử với khai báo khoảng range riêng | |
Range firstFourRange = ..4 | |
var firstFour = people[firstFourRange]; // Lấy ra 4 phần tử đầu tiên "Jane", "Jean", "Grey", and "Marcus" | |
Range lastTwoElement = ^2.. | |
var lastTwo = people[lastTwoElement] // Lấy ra 2 phần tử cuối cùng "Theophilus" and "Keje" | |
Index lastIndex = ^1; // Khai báo chỉ số | |
string value = people[lastIndex]; // Lấy giá trị theo chỉ số | |
//-------------------------------------------------------------------------------------- | |
// 2. Static Local Functions | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// Khai báo hàm bên trong hàm | |
public string MethodWithLocalFunction() | |
{ | |
string firstname = "Tuan"; | |
string lastname = "Nguyen"; | |
return LocalFunction(); | |
string LocalFunction() => firstname + " - " + lastname; | |
} | |
//-------------------------------------------------------------------------------------- | |
// Khai báo hàm static bên trong hàm | |
public string MethodWithLocalFunction() | |
{ | |
string first = "Nguyen"; | |
string last = "Tuan"; | |
return LocalFunction(first, last); | |
static string LocalFunction(string firstname, string lastname) => firstname + " - " + lastname; | |
} | |
//-------------------------------------------------------------------------------------- | |
// 3. Using Declaration | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// Với các phiên bản trước đó | |
void ReadFile(string path) | |
{ | |
// Lồng nhiều using rất bất tiện và khó đọc | |
using (FileStream fs = File.OpenRead(path)) // using declaration | |
{ | |
byte[] b = new byte[1024]; | |
UTF8Encoding temp = new UTF8Encoding(true); | |
while (fs.Read(b,0,b.Length) > 0) | |
{ | |
Console.WriteLine(temp.GetString(b)); | |
} | |
} | |
} | |
//-------------------------------------------------------------------------------------- | |
// Khai báo using tiện lợi hơn với C# 8 | |
void ReadFile(string path) | |
{ | |
using FileStream fs = File.OpenRead(path); // using declaration | |
byte[] b = new byte[1024]; | |
UTF8Encoding temp = new UTF8Encoding(true); | |
while (fs.Read(b,0,b.Length) > 0) | |
{ | |
Console.WriteLine(temp.GetString(b)); | |
} | |
// fs is disposed here | |
} | |
//-------------------------------------------------------------------------------------- | |
// 4. Readonly Members | |
//-------------------------------------------------------------------------------------- | |
public struct Point | |
{ | |
public double X { get; set; } | |
public double Y { get; set; } | |
public double Distance => Math.Sqrt(X * X + Y * Y); | |
public override string ToString() => | |
$"({X}, {Y}) is {Distance} from the origin"; | |
} | |
//-------------------------------------------------------------------------------------- | |
// Khai báo readonly | |
public readonly double Distance => Math.Sqrt(X * X + Y * Y); | |
public readonly override string ToString() => $"({X}, {Y}) is {Distance} from the origin"; | |
public readonly void Translate(int xOffset, int yOffset) | |
{ | |
X += xOffset; | |
Y += yOffset; | |
} | |
//-------------------------------------------------------------------------------------- | |
// 5. Pattern Matching - Switch Expressions | |
//-------------------------------------------------------------------------------------- | |
public enum Rainbow | |
{ | |
Red, | |
Orange, | |
Yellow, | |
Green, | |
Blue, | |
Indigo, | |
Violet | |
} | |
//-------------------------------------------------------------------------------------- | |
// Các phiên bản trước | |
public static RGBColor FromRainbowClassic(Rainbow colorBand) | |
{ | |
switch (colorBand) | |
{ | |
case Rainbow.Red: | |
return new RGBColor(0xFF, 0x00, 0x00); | |
case Rainbow.Orange: | |
return new RGBColor(0xFF, 0x7F, 0x00); | |
case Rainbow.Yellow: | |
return new RGBColor(0xFF, 0xFF, 0x00); | |
case Rainbow.Green: | |
return new RGBColor(0x00, 0xFF, 0x00); | |
case Rainbow.Blue: | |
return new RGBColor(0x00, 0x00, 0xFF); | |
case Rainbow.Indigo: | |
return new RGBColor(0x4B, 0x00, 0x82); | |
case Rainbow.Violet: | |
return new RGBColor(0x94, 0x00, 0xD3); | |
default: | |
throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)); | |
}; | |
} | |
//-------------------------------------------------------------------------------------- | |
// C# 8 dùng switch trong câu lệnh | |
public static RGBColor FromRainbow(Rainbow colorBand) => | |
colorBand switch | |
{ | |
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00), | |
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00), | |
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00), | |
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00), | |
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF), | |
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82), | |
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3), | |
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)), | |
}; | |
//-------------------------------------------------------------------------------------- | |
// Dùng switch kết hợp với property (Property pattern) | |
public static decimal ComputeSalesTax(Address location, decimal salePrice) => | |
location switch | |
{ | |
{ State: "WA" } => salePrice * 0.06M, | |
{ State: "MN" } => salePrice * 0.75M, | |
{ State: "MI" } => salePrice * 0.05M, | |
// other cases removed for brevity... | |
_ => 0M | |
}; | |
//-------------------------------------------------------------------------------------- | |
// Dùng switch kết hợp với Tuple (Tuple pattern) | |
public static string RockPaperScissors(string first, string second) | |
=> (first, second) switch | |
{ | |
("rock", "paper") => "rock is covered by paper. Paper wins.", | |
("rock", "scissors") => "rock breaks scissors. Rock wins.", | |
("paper", "rock") => "paper covers rock. Paper wins.", | |
("paper", "scissors") => "paper is cut by scissors. Scissors wins.", | |
("scissors", "rock") => "scissors is broken by rock. Rock wins.", | |
("scissors", "paper") => "scissors cuts paper. Scissors wins.", | |
(_, _) => "tie" | |
}; | |
//-------------------------------------------------------------------------------------- | |
// Positonal pattern | |
public enum Quadrant | |
{ | |
Unknown, | |
Origin, | |
One, | |
Two, | |
Three, | |
Four, | |
OnBorder | |
} | |
static Quadrant GetQuadrant(Point point) => point switch | |
{ | |
(0, 0) => Quadrant.Origin, | |
var (x, y) when x > 0 && y > 0 => Quadrant.One, | |
var (x, y) when x < 0 && y > 0 => Quadrant.Two, | |
var (x, y) when x < 0 && y < 0 => Quadrant.Three, | |
var (x, y) when x > 0 && y < 0 => Quadrant.Four, | |
var (_, _) => Quadrant.OnBorder, | |
_ => Quadrant.Unknown | |
}; | |
//-------------------------------------------------------------------------------------- | |
// 6. Asynchronous streams | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// Tạo và sử dụng stream bất đồng bộ | |
public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence() | |
{ | |
for (int i = 0; i < 20; i++) | |
{ | |
await Task.Delay(100); | |
yield return i; | |
} | |
} | |
await foreach (var number in GenerateSequence()) | |
{ | |
Console.WriteLine(number); | |
} | |
//-------------------------------------------------------------------------------------- | |
// 7. Nullable References | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
class Student | |
{ | |
public string FirstName {get; set;} | |
public string LastName {get; set;} | |
public Student(string firstName) | |
{ | |
FirstName = firstName; | |
} | |
} | |
public void PrintInfo(Student student) | |
{ | |
return $"{student.FirstName} {student.LastName}" | |
} | |
var student = new Student("Tuan"); | |
// Dính lỗi NullReferenceException do LastName không được khởi tạo | |
PrintInfo(student); | |
// C#8 giúp ta có thể detect sớm vấn đề này bằng cách sử dụng #nullable enabled | |
#nullable enabled | |
class Student | |
{ | |
public string FirstName {get; set;} | |
public string LastName {get; set;} | |
public Student(string firstName) | |
{ | |
FirstName = firstName; | |
} | |
} | |
public void PrintInfo(Student student) | |
{ | |
// Sẽ có cảnh báo ở dòng này | |
return $"{student.FirstName} {student.LastName}" | |
} | |
// Sửa lại bằng cách kiểm tra null | |
public void PrintInfo(Student student) | |
{ | |
if(student != null) | |
return $"{student.FirstName} {student.LastName}" | |
else | |
return $"{student.FirstName}" | |
} | |
//-------------------------------------------------------------------------------------- | |
// 8. Default Interface Member | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// Khai báo interface với default implementation | |
interface ILogger | |
{ | |
void Log(LogLevel level, string message); | |
void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); | |
} | |
public static void LogException(ConsoleLogger logger, Exception ex) | |
{ | |
ILogger ilogger = logger; // Converting to interface | |
ilogger.Log(ex); // Calling new Log overload | |
} | |
//-------------------------------------------------------------------------------------- | |
// 9. Disposable ref structs | |
//-------------------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------------------- | |
// Khai báo ref struct với hàm hủy | |
ref struct Book | |
{ | |
public void Dispose() | |
{ | |
} | |
} | |
using var book = new Book(); | |
// ... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment