Các tính năng mới của C# 6.0

Microsoft ra mắt C# 6.0 đi kèm với .NET Framework 4.6 và Visual Studio 2015. Bài viết này sẽ trình bày về các tính năng mới được bổ sung trong C# 6.0.

Thuộc tính tự động chỉ đọc

Thuộc tính tự động chỉ đọc (auto-property read-only) cung cấp một cú pháp ngắn gọn hơn để tạo các thuộc tính chỉ đọc. Bạn khai báo thuộc tính tự động chỉ đọc như sau:

public string FirstName { get; }
public string LastName { get; }

Các thuộc tính FirstNameLastName chỉ có thể được gán giá trị trong phương thức khởi tạo của lớp.

public Student(string firstName, string lastName)
{
    FirstName = firstName;
    LastName = lastName;
}

Cố gắng gán giá trị cho thuộc tính tự động chỉ đọc ở những phương thức khác sẽ bị lỗi khi biên dịch.

Khởi tạo thuộc tính tự động

Khởi tạo thuộc tính tự động (auto-property initializers) cho phép bạn khai báo giá trị ban đầu cho thuộc tính tự động như một phần của khai báo thuộc tính.

public ICollection<double> Grades { get; } = new List<double>();

Như vậy, ngoài cách gán giá trị cho thuộc tính tự động chỉ đọc tại phương thức khởi tạo của lớp, chúng ta có thể gán giá trị ngay khi khai báo thuộc tính.

Cú pháp thân chức năng

Cú pháp này rút gọn phần thân cho các phương thức và thuộc tính chỉ đọc. Ví dụ minh họa cho phương thức ToString():

public string FirstName { get; }
public string LastName { get; }

public override string ToString() => $"{LastName}, {FirstName}";

Bạn cũng có thể sử dụng cú pháp này cho các thuộc tính chỉ đọc:

public string FirstName { get; }
public string LastName { get; }
public string FullName => $"{FirstName} {LastName}";

using static

using static cho phép bạn sử dụng trực tiếp các thành phần tĩnh của một lớp. Bạn khai báo lớp bạn muốn sử dụng như sau:

using static System.Math;

Ví dụ minh họa using static System.Math:

using System;
using static System.Math;

public class Circle
{
   public Circle(double radius)
   {
      Radius = radius;
   }

   public double Radius { get; set; }

   public double Area
   {
      get { return PI * Pow(Radius, 2); }
   }
}

Thay vì khai báo Math.PI để sử dụng hằng số Pi và phương thức Math.Pow để tính lũy thừa thì bây giờ bạn chỉ cần khai báo PI và Pow là xong.

Toán tử ?.

Toán tử ?. sẽ kiểm tra biến có bị null hay không trước khi truy cập các thuộc tính của biến.

var first = person?.FirstName;

Như ví dụ trên, nếu biến person khác null thì nó sẽ trả về giá trị của thuộc tính FirstName, ngược lại nó sẽ trả về null.

Nếu không sử dụng toán tử ?. thì bạn phải viết code như sau để tránh bị lỗi khi biến person bị null.

if (person != null)
{
    var first = person.FirstName;
}

Nếu bạn muốn gán giá trị mặc định khi biến person null thì có thể viết như sau:

var first = person?.FirstName ?? "N/A";

Nối chuỗi

Với C# 6.0, bạn có thể sử dụng toán tử $ và cặp dấu {} để nối chuỗi nhanh chóng và trực quan. Hãy xem ví dụ sau:

var firstName = "Trung";
var lastName = "Nguyen";
var fullName = $"{firstName} {lastName}"; // -> Trung Nguyen

Bộ lọc ngoại lệ

Bộ lọc ngoại lệ được sử dụng trên khối catch bằng cách sử dụng từ khóa when và một biểu thức. Khi có ngoại lệ xảy ra, nếu biểu thức của khối catch trả về true thì khối catch mới được thực thi, ngược lại sẽ bỏ qua khối catch.

public static async Task<string> MakeRequest()
{
    WebRequestHandler webRequestHandler = new WebRequestHandler();
    webRequestHandler.AllowAutoRedirect = false;
    using (HttpClient client = new HttpClient(webRequestHandler))
    {
        var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");
        try
        {
            var responseText = await stringTask;
            return responseText;
        }
        catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
        {
            return "Site Moved";
        }
    }
}

Biểu thức nameof

Biểu thức nameof sẽ trả về tên của một đối tượng bất kỳ. Nó giúp bạn tránh phải hard code tên của phần tử khi ghi log hoặc ném ra ngoại lệ. Bạn sẽ yêu nó rất nhiều đấy.

public Student(string firstName, string lastName)
{
    if (IsNullOrWhiteSpace(lastName))
        throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
    FirstName = firstName;
    LastName = lastName;
}

await trong khối catch và finally

Với C# 6, bạn đã có thể sử dụng từ khóa await trong khối catchfinally như sau:

public static async Task<string> MakeRequestAndLogFailures()
{ 
    await LogMethodEntrance();
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try 
    {
        var responseText = await streamTask;
        return responseText;
    } 
    catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    {
        await LogError("Recovered from redirect", e);
        return "Site Moved";
    }
    finally
    {
        await LogMethodExit();
        client.Dispose();
    }
}

Khởi tạo danh sách bằng bộ chỉ mục

Bạn có thể sử dụng cú pháp khởi tạo để khởi tạo nhanh cho danh sách như sau:

private Dictionary<int, string> messages = new Dictionary<int, string>
{
    { 404, "Page not Found"},
    { 302, "Page moved, but left a forwarding address."},
    { 500, "The web server can't come out to play today."}
};

Với C# 6, bạn có thể khởi tạo danh sách sử dụng chỉ mục như sau:

private Dictionary<int, string> webErrors = new Dictionary<int, string>
{
    [404] = "Page not Found",
    [302] = "Page moved, but left a forwarding address.",
    [500] = "The web server can't come out to play today."
};
Lập Trình C#Tính năng mới của C#
Bài Viết Liên Quan:
int[] và int[,] trong C#: Ai nhanh hơn
Trung Nguyen 10/10/2020
int[] và int[,] trong C#: Ai nhanh hơn

Hiểu được sự khác biệt giữa các loại mảng trong C# sẽ giúp bạn chọn cấu trúc dữ liệu chính xác cho mọi trường hợp.

Struct và class trong C#: Ai nhanh hơn
Trung Nguyen 09/10/2020
Struct và class trong C#: Ai nhanh hơn

Trong bài viết này, tôi sẽ so sánh sự khác biệt về hiệu suất giữa struct và class trong C#: Ai nhanh hơn.

Best practice cho performance trong C#
Trung Nguyen 03/10/2020
Best practice cho performance trong C#

Mục tiêu của bài viết này là cung cấp một danh sách không đầy đủ các code mẫu cần tránh, vì chúng rủi ro hoặc performance kém.

Đọc ghi file (File I/O) trong C#
Trung Nguyen 26/04/2020
Đọc ghi file (File I/O) trong C#

Hướng dẫn này sẽ giúp bạn tìm hiểu về đọc ghi file (File I/O) trong C# và sử dụng các lớp tiện ích để đọc ghi file.