Những điểm mới trong C# 6 là gì


Tìm hiểu C# 6 trong bộ Visual Studio 2015 có những gì mạnh mẽ và đáng sử dụng nào


Tóm tắt lịch sử phát triển của C#

  • C# 1.0 2002 => Hello, World!
  • C# 2.0 2005 => Generic<T>
  • C# 3.0 2007 => cs => cs.Linq
  • C# 4.0 2010 => dynamic
  • C# 5.0 2012 => async 
  • C# 6.0 2015 => ????

1. Tự động gắn giá trị cho thuộc tính

Ở các phiên bản trước

public class User
{
    Guid _id = Guid.NewGuid();
    public Guid ID
    {
        get { return _id; }
    }
}

Trong C# 6.0

public class User
{
    public Guid ID { get; } = Guid.NewGuid();
}

2. Thuộc tính chỉ cho phép đọc Primary Constructors

Ở các phiên bản trước

public class Money
{
    public string Current { get; private set; }
    public decimal Amount { get; private set; }
    public Money(string currency, decimal amount)
    {
        Current = currency;
        Amount = amount;
    }
}

Trong C# 6.0

public class Money
{
    public string Currency { get; } = "VND";
    public decimal Amount { get; } = 1000;
}

hoặc được gắn trong constructor

public class Money
{
    public string Current { get; }
    public decimal Amount { get; }
    public Money(string currency, decimal amount)
    {
        Current = currency;
        Amount = amount;
    }
}

3. Khai báo biểu thức

Ở các phiên bản trước

var numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
int result = 0;
var odd = numbers.Where(n => n % 2 == 1).ToList();
foreach (var item in odd)
{
    result += item + odd.Count();
}
return result;

Trong C# 6.0

var numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
int result = 0;
foreach (var item in var odd = numbers.Where(n => n % 2 == 1).ToList())
{
    result += item + odd.Count();
}
return result;

4. Using Static

Ở các phiên bản trước

using System;
class Program
{
    public static void Main()
    {
        Console.WriteLine("Welcome MasterCode.vn");
    }
}

Trong C# 6.0

using static System.Console;
class Program
{
    public static void Main()
    {
        WriteLine("Welcome MasterCode.vn");
    }
}

Bạn dùng using static để đăng ký lớp static cần sử dụng là lớp Console. Trong Main(), bạn không cần gõ lại lớp Console mà dùng ngay WriteLine()

5. Sử dụng toán tử điều kiện null

Ở các phiên bản trước

string name = "Võ Nhật Nam";
if (customer != null)
{
    name = customer.Name;
}

Trong C# 6.0

string name = customer?.Name ?? "Võ Nhật Nam";

Kí hiệu ?. dùng để kiểm tra giá trị bên trái nó (customer) có phải null hay không. Nếu là null thì nó trả về null. Còn không, nó sẽ đi tiếp sang giá trị bên phải (Name) và kiểm tra null. Nếu giá trị này không phải null thì trả về giá trị đó.

Dấu ?? là toán tử null-coalescing. Nếu biểu thức bên trái có giá trị khác null thì trả về giá trị đó, nếu là null thì trả về giá trị bên phải. Toán tử này có từ các phiên bản trước của C#, và khi phối hợp với ?., bạn có một dòng code thực hiện chức năng của 5 dòng code ở trên.

6. Biểu thức nameof

Ở các phiên bản trước

public static void DoWork(string name)
{
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
}

Khi xử lý ngoại lệ, bạn kèm tên biến vào trong thông báo lỗi để sau này dễ dàng tìm kiếm. Tuy nhiên, vấn đề nảy sinh khi ta thay đổi tên biến. Lúc này, thông báo lỗi không còn chỉ ra đúng tên biến gây lỗi. Do vậy, C# 6.0 giới thiệu toán tử nameof nhằm lấy ra tên biến mà không phải gõ trực tiếp vào chuỗi.

public static void DoWork(string name)
{
    if (name == null)
    {
        throw new ArgumentNullException(nameof(name));
    }
}

7. Thay phần thân method và property bằng biểu thức

Ở các phiên bản trước

public class Student
{
    public string Name { get; set; }
    public int BirthYear { get; set; }
    public int Age
    {
        get
        {
            return DateTime.Now.Year - BirthYear;
        }
    }

    public override string ToString()
    {
        return "Name: " + this.Name;
    }
}

Trong C# 6.0

public class Student
{
    public string Name { get; set; }
    public int BirthYear { get; set; }
    public int Age => DateTime.Now.Year - BirthYear;
    public override string ToString() => "Name: " + this.Name;
}

Ở dòng 5, Age đã được chuyển sang cú pháp lambda. Thay vì cung cấp get, ta dùng mũi tên mập (fat arrow). Thậm chí ta không cần dùng từ khóa return, C# sẽ tự động trả về giá trị của biểu thức sau dấu =>. Tương tự, tại dòng 6, ToString() cũng sử dụng cú pháp lambda.

8. Chèn giá trị vào trong chuỗi

Để định dạng chuỗi, ta phải dùng string.Format(). Cách làm này dài dòng nên dễ dẫn đến sai sót.

public override string ToString() => string.Format("Name: {0}", this.Name);

Để định dạng chuỗi, ta phải dùng string.Format(). Cách làm này dài dòng nên dễ dẫn đến sai sót.

public override string ToString() => $"Name: {this.Name}";

Bạn bắt đầu chuỗi bằng dấu $. Tiếp theo, ta chèn tên biến vào chuỗi và bao quanh bằng cặp dấu ngoặc nhọn. Kết quả của hai dòng lệnh trên là giống nhau, nhưng dòng lệnh dưới trông dễ đọc hơn.

9. Gán giá trị ban đầu cho collection bằng cú pháp chỉ số index

Ở các phiên bản trước

Dictionary<string, User> users = new Dictionary<string, User>()
{
     { "admin", new User("admin@mastercode.vn") },
     { "user", new User("vonhatnam") }
};

Như bạn thấy, dòng lệnh 3 và 4 rất mơ hồ. Cú pháp này không chỉ ra rõ ràng chuỗi manager là key và new User() là value. Trong C# 6.0, bạn có thể dùng cú pháp chỉ số index để gán giá trị. Cú pháp này thể hiện rõ đâu là key và đâu là value.

Dictionary<string, User> users = new Dictionary<string, User>()
{
     ["admin"] = new User("admin@mastercode.vn"),
     ["users"] = new User("vonhatnam")
};

10. Lọc ngoại lệ

Bắt ngoại lệ bằng cú pháp try...catch là thao tác quen thuộc của lập trình viên. Với cú pháp này, ta chỉ bắt được ngoại lệ dựa trên kiểu của nó. Trong C# 6.0, Microsoft bổ sung thêm tính năng lọc ngoại lệ bằng cách kiểm tra một điều kiện cho trước.

try
{
    // Statements
}
catch (Exception ex) when (ex.Data.Count > 0)
{
     // Handle exception
}

Ta khai báo điều kiện lọc bằng từ khóa when và theo sau là một biểu thức điều kiện (trả về true hoặc false). Nếu thỏa điều kiện, khối lệnh của catch sẽ được thực thi.

11. Dùng từ khóa await trong khối lệnh catch và finally

Nếu dùng từ khóa await trong khối lệnh catch ở các phiên bản C# trước, ta sẽ nhận thông báo lỗi bảo rằng await không thể dùng trong catch. Vì kĩ thuật lập trình bất đồng bộ đang ngày càng trở nên cần thiết trong ứng dụng hiện đại, nên việc không cho dùng await trong catch là một trở ngại lớn. Do đó, phiên bản C# 6.0 đã cho phép dùng await trong khối catch.

try
{
    // Statements
}
catch (Exception ex)
{
    await FileHelper.WriteAsync(ex.Message);
}

Chia sẽ bài viết :